2010-02-19 9 views
5

¿Es posible escribir una clase:Posible pasar el nombre como argumento a la plantilla de C++?

template<typename T, ... name> struct Magic { 
    T name; 
}; 

tal que:

Magic<int, foo> gives: 

Magic<int, foo> { 
    int foo; 
} 

y

Magic<float, bar> gives: 

Magic<float, bar> { 
    float bar; 
} 

Básicamente, quiero ser capaz de especificar no sólo el tipo, pero también el nombre de las variables miembro.

+0

Plantillas de tipos de control. Los únicos nombres a los que pueden hacer referencia son nombres de tipos, no nombres léxicos. El preprocesador es para nombres léxicos. – GManNickG

+0

la única forma en que puedo pensar es en usar el patrón inheritance + crtp, como 'struct bar_variable {float bar; }; struct Magic : named_variable {}; Magic ; ' – Anycorn

Respuesta

5

Eso no es posible, debe recurrir a soluciones basadas en macros o utilizar un conjunto predefinido de tipos que proporcionan miembros con nombre.

Un posible enfoque basado en la macro:

#define MAGIC(name_) \ 
    template<typename T> struct Magic1 { \ 
     T name_; \ 
    }; 

MAGIC(foo); 

o:

#define MAGIC(type_, name_) \ 
    struct Magic1 { \ 
     type_ name_; \ 
    }; 

MAGIC(foo); 

Usando magia preprocesador, por ejemplo utilizando Boost.Preprocessor, debe poder generar n miembros nombrados de una manera más conveniente.

Otro enfoque podría ser el uso de un conjunto predefinido de clases que proporcionan ciertos representantes nombrados en que se hereda:

enum { MemberNameFoo, MemberNameBar }; 

template<class T, int id> 
struct named_member; 

template<class T> 
struct named_member<T, MemberNameFoo> { 
    T foo; 
}; 

template<class T> 
struct named_member<T, MemberNameBar> { 
    T bar; 
}; 

// holder for the above, just one member for this example: 

template<class T, int name> 
struct holder : named_member<T, name> {}; 

// using it: 

typedef holder<int, MemberNameFoo> HasFoo; 
typedef holder<int, MemberNameBar> HasBar; 

El uso de tiempo de compilación listas que luego podría heredar de nnamed_member ejemplificaciones, Boost.MPL podría ayudar aquí .

+0

Si realmente no te importa demasiado el nombre exacto de tus miembros, puedes hacerlo con listas de tipos o en plantillas variadas de C++ 0x. Lo hice para implementar clases que escribieran sus propios métodos de serialización y deserialización. – Omnifarious

+0

Pero la pregunta es si es * "posible pasar nombres [s]" * a una plantilla, no cómo generar un titular para una colección de tipos arbitrariamente nombrada. –

+0

@gf, esto es cierto. Aunque a menudo las personas no hacen la pregunta que quieren decir exactamente. Tienen una solución en mente para un problema y preguntan cómo hacer que la solución funcione, no cómo resolver el problema real.:-) – Omnifarious

1

No, no es posible. Existe un constructo llamado typelist que se puede usar para lograr un efecto similar al que busca. Desafortunadamente, incluso entonces no obtendrá miembros con nombre, obtendrá funciones de acceso con nombres como MyClass::getField<1>().

En C++ 0x puede hacer mejor que las listas de tipos con variadic templates. Pero todavía tendrá funciones de acceso que se parecen a las de C++.

Es tentador poner aquí un ejemplo de plantilla variadic porque no sería demasiado grande. Desafortunadamente, creo que hacerlo bien requeriría algunas horas de investigación de mi parte para aprender exactamente cómo funcionaban las plantillas variadas. Podría hacer una versión estúpida con relativa facilidad, pero espero que la estúpida versión sea mucho menos agradable de varias maneras que una versión bien hecha.

Cuestiones relacionadas