referencias programacion posible numeros mayor los lenguaje intencionada ingresar elementos determinar cual comparar comparacion como codigos arreglo c++ templates

c++ - programacion - posible comparacion de referencias no intencionada c#



¿Cómo comparar dos nombres para la igualdad en C++? (5)

Supongamos que tengo una plantilla de una función, digamos

template<typename T> func(T a, T b, ...) { ... for (const auto &single : group) { ... auto c = GivenFunc1(a, b, single, ...); ... } ... }

Sin embargo, para que T sea un tipo especial, diga "SpecialType", quiero que c se calcule con "GivenFunc2" en lugar de "GivenFunc1". Sin embargo, no me gustaría escribir una especialización para "SpecialType", ya que habrá una gran duplicación de código. Así que quiero que la función de plantilla sea algo como

template<typename T> func(T a, T b, ...) { ... for (const auto &single : group) { ... auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...) : GivenFunc1(a, b, single, ...); ... } ... }

Por supuesto, este código no se compila ya que "T == SpecialType" no es válido. Entonces, ¿cómo lo escribo de una manera elegante?


Convierte GivenFunc1 en un funtor y especialízalo.

template <class T> class GivenFunc { X operator()(T a, T b, Y single) { ... } } template <> class GivenFunc<SpecialType> { X operator()(SpecialType a, SpecialType b, Y single) { ... } }

Entonces puedes decir

auto c = GivenFunc<T>()(a, b, single);


En c ++ 17 la mejor solución es if constexpr .

En c ++ 14 esto funciona:

template<class V> auto dispatch( V const& ) { return [](auto&&...targets) { return std::get<V{}>( std::forward_as_tuple( decltype(targets)(targets)... ) ); }; }

entonces:

auto c = dispatch( std::is_same<T, SpecialType>{} ) ( [&](auto&& a, auto&& b){ return GivenFunc2(a, b, single...); }, [&](auto&& a, auto&& b){ return GivenFunc1(a, b, single, ...); } )( a, b );

hace lo que quieras (También es una función que devuelve una función que devuelve una función)

Ejemplo vivo .

dispatch selecciona uno de los dos lambdas y lo devuelve en tiempo de compilación. Luego llamamos a la lambda elegida con a y b . Por lo tanto, solo el válido se compila con un tipo para a y b .


Es tan simple como:

auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...) : GivenFunc1(a, b, single, ...);

Si no puede usar C ++ 17, reemplace std::is_same_v<...> con std::is_same<...>::value .

Pero para que este enfoque funcione, ambas llamadas de función tienen que ser válidas para cada T que quieras usar, incluso si en realidad una de ellas no se ejecutará.

Si no es el caso, puede recurrir if constexpr :

your_type_here c; if constexpr (std::is_same_v<T, SpecialType>) c = GivenFunc2(a, b, single, ...); else c = GivenFunc1(a, b, single, ...);

(Esto funciona solo en C ++ 17.)


Si puede usar C ++ 17 , puede lograr el resultado de una manera muy limpia (con constexpr y is_same ):

template<typename T> func(T a, T b, ...) { // ... if constexpr (std::is_same_v<T, SpecialType>) { // call GivenFunc2 } else { // call GivenFunc1 } // ... }

Antes de C ++ 17 , puede lograr el mismo resultado utilizando técnicas como SFINAE o "Despacho de TAG".

Además, puede simplemente especializar la parte del código que se refiere a la llamada a la función (fácil y evitar la duplicación de código).

Un breve ejemplo here :

template <typename T> struct DispatcherFn { auto operator()(const T&, int) { // call GivenFunc1 } }; template <> struct DispatcherFn<SpecialType> { auto operator()(const SpecialType&, int) { // GivenFunc2 } }; template <typename T> void func(const T& t) { // ... code ... auto c = DispatcherFn<T>()(t, 49); // specialized call }


Siempre puede usar las especializaciones de plantillas en lugar de hacer comparaciones de tipos de parámetros de plantillas. Aquí hay un ejemplo de trabajo simplificado:

#include <iostream> #include <string> template<typename T> int GivenFunc1(T a, T b) { std::cout << "GivenFunc1()" << std::endl; return 0; } template<typename T> int GivenFunc2(T a, T b) { std::cout << "GivenFunc2()" << std::endl; return 1; } template<typename T> void func(T a, T b) { auto c = GivenFunc2(a, b); std::cout << c << std::endl; } template<> void func(std::string a, std::string b) { auto c = GivenFunc1(a, b); std::cout << c << std::endl; } int main() { func(2,3); std::string a = "Hello"; std::string b = "World"; func(a,b); }

Véalo trabajando en línea aquí .