template safe plantillas linebreaksbr length ifequal c++ templates dry generic-programming

c++ - safe - linebreaksbr django



FunciĆ³n de plantilla como argumento de plantilla. (3)

Para resolver este problema con las plantillas, debe utilizar un parámetro de plantilla de plantilla. Desafortunadamente, no puede pasar la plantilla de plantilla de plantilla como un tipo, ya que primero debe ser instanciada. Pero hay una solución con estructuras ficticias. Aquí hay un ejemplo:

template <typename T> struct a { static void foo (T = T ()) { } }; template <typename T> struct b { static void foo (T = T ()) { } }; struct SomeObj {}; struct SomeOtherObj {}; template <template <typename P> class T> void function () { T<SomeObj>::foo (); T<SomeOtherObj>::foo (); } int main () { function<a>(); function<b>(); }

Acabo de confundirme cómo implementar algo de una manera genérica en C ++. Es un poco complicado, así que déjame explicarte paso a paso.

Considere dicho código:

void a(int) { // do something } void b(int) { // something else } void function1() { a(123); a(456); } void function2() { b(123); b(456); } void test() { function1(); function2(); }

Es fácil notar que function1 y function2 hacen lo mismo, con la única parte diferente que es la función interna.

Por lo tanto, quiero hacer una function genérica para evitar la redundancia de código. Puedo hacerlo usando punteros de función o plantillas. Déjame elegir lo último por ahora. Mi opinión es que es mejor, ya que el compilador seguramente podrá integrar las funciones, ¿estoy en lo cierto? ¿Pueden los compiladores seguir incorporando las llamadas si se realizan a través de punteros de función? Esta es una pregunta lateral.

Bien, volviendo al punto original ... Una solución con plantillas:

void a(int) { // do something } void b(int) { // something else } template<void (*param)(int) > void function() { param(123); param(456); } void test() { function<a>(); function<b>(); }

Todo bien. Pero tengo un problema: ¿puedo seguir haciendo eso si b son genéricos en sí mismos?

template<typename T> void a(T t) { // do something } template<typename T> void b(T t) { // something else } template< ...param... > // ??? void function() { param<SomeType>(someobj); param<AnotherType>(someotherobj); } void test() { function<a>(); function<b>(); }

Sé que un parámetro de plantilla puede ser uno de:

  • un tipo,
  • un tipo de plantilla,
  • un valor de un tipo.

Nada de eso parece cubrir mi situación. Por lo tanto, mi pregunta principal es: ¿cómo resuelvo eso, es decir, defino function() en el último ejemplo?

(Sí, los punteros de función parecen ser una solución en este caso exacto, siempre que también puedan estar en línea, pero estoy buscando una solución general para esta clase de problemas).


Aquí hay una manera. Puede que no sea el mejor, pero funciona:

template <typename T, T param> void function() { param(123); param(456); } void test() { function< void(*)(int), a<int> >(); // space at end necessary to compiler function< void(*)(int), b<int> >(); // because the C++ grammar is ambiguous }

El hecho de que estén o no en línea depende del compilador, pero me sorprendería si no lo estuvieran.

EDIT: Bueno, hoy estoy un poco fuera de lugar y me perdí la parte donde los parámetros son de diferentes tipos. Mi error.

Puede haber una manera difícil de hacer esto con las plantillas, pero esta es la forma más fácil que se me ocurre:

#define function(x) do { x<thing1>(obj1); x<thing2>(obj2) } while(0)

Lo sé, lo sé, "las macros son malvadas", bla bla bla. Funciona. Si la function necesita ser más complicada que su ejemplo, es posible que tenga problemas, pero es mucho más fácil que cualquier cosa que haya podido encontrar.


template < typename F > void function(F f) { f(123); } void a(int x) { ... } struct b { void operator() (int x) { ... } }; void outer() { function(&a); function(b()); }