visual studio microsoft español descargar community c++ templates macros function-pointers

c++ - microsoft - visual studio installer



Puntero de función única C++ para todas las instancias de plantilla (2)

Lo que estás tratando de lograr con

void testAcrossTypes(SomeType f) { f<int> (); f<bool> (); f<char> (); f<double> (); }

sería posible si SomeType pudiera ser un argumento de plantilla de plantilla. Sin embargo, el estándar no permite plantillas de funciones como argumento de plantilla de plantilla.

Del estándar C ++ 11:

14.3.3 Argumentos de plantilla de plantilla

1 Una plantilla-argumento para una plantilla plantilla-parámetro será el nombre de una plantilla de clase o una plantilla de alias, expresada como expresión-id.

Su mejor opción es usar funtores en lugar de funciones. Ejemplo:

template<typename T> struct function1 { void operator()() { return; } }; template<typename T> struct function2 { void operator()() { return; } }; template < template <typename> class F> void testAcrossTypes() { F<int>()(); F<bool>()(); F<char>()(); F<double>()(); } int main() { testAcrossTypes<function1>(); testAcrossTypes<function2>(); }

¿Hay una forma concisa para apuntar a todas las instancias de una función de plantilla sin usar macros?

Tengo varias funciones de plantilla que quiero probar en una variedad de tipos:

template<typename T> void function1() { return; } template<typename T> void function2() { return; } template<typename T> void function3() { return; }

Puedo hacer esto con una macro:

#define TEST_ACROSS_TYPES(fn) / fn<int>(); / fn<bool>(); / fn<char>(); / fn<double>(); / TEST_ACROSS_TYPES(function1); TEST_ACROSS_TYPES(function2);

Pero, (1) las macros son feas y difíciles de seguir para otros, y (2) estoy usando CATCH , que no funciona bien cuando se usan macros para configurar casos de prueba.

¿Hay alguna manera de hacer algo como esto?

void testAcrossTypes(SomeType f) { f<int> (); f<bool> (); f<char> (); f<double> (); }

que parece mucho más limpio, excepto por el problema de definir SomeType . Esta pregunta ( Cómo definir el tipo de deflector de función que tiene argumentos de plantilla ) explica cómo definir un puntero a una función de plantilla; pero requiere que se especifiquen los argumentos de la plantilla.

Para aclarar: Imagine function1 , function2 y function3 cada prueba una función diferente de plantilla. Cada función necesita ser probada para int , byte , char , double , etc. Quiero evitar tener que configurar explícitamente muchas (es decir, num_functions * num_types) pruebas para cada función. En cambio, quiero tener un único método que apunte a la función de prueba ( function1 , function2 , etc.) y la ejecute para cada tipo de plantilla, consolidando así

function1<int>(); function1<byte>(); function1<char>(); function1<double(); ... function2<int>(); function2<byte>(); function2<char>(); function2<double(); ... function3<int>(); function3<byte>(); function3<char>(); function3<double(); ...

en una sola llamada por función de prueba

testAcrossTypes(function1); testAcrossTypes(function2); testAcrossTypes(function3);


Puedes lograrlo por medio de un functor borrado, como el del siguiente ejemplo:

#include<vector> template<typename T> void function1() { } template<typename T> void function2() { } template<typename T> void function3() { } struct Test { template<typename T> static void proto() { function1<T>(); function2<T>(); function3<T>(); } void operator()() { for(auto &f: vec) f(); } template<typename... T> static Test create() { Test test; int arr[] = { (test.vec.emplace_back(&proto<T>), 0)... }; (void)arr; return test; } using func = void(*)(void); std::vector<func> vec; }; void testAcrossTypes(Test test) { test(); } int main() { testAcrossTypes(Test::create<int, bool, char, double>()); }

Es fácil de modificar en ambos casos:

  • Se deben agregar nuevas funciones al método de miembro proto estático y eso es todo

  • Agregar un nuevo tipo es una cuestión de usarlo cuando se create llamada, como se muestra en el ejemplo anterior

El funtor se encargará de crear las llamadas N * M para ser ejecutadas.
Además, no necesita mover sus funciones en un conjunto de estructuras para poder usarlas.