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 todoAgregar 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.