2010-12-14 19 views
5

¿Hay alguna forma de generar el nombre de una variable dentro de una clase basada en un argumento template?Nombre de variable del argumento de plantilla?

template<class T, (someconstruct) t> 

class Item { 
    public:   
     T t; 
}; 

Item<float, "Position"> myItem; 

myItem.Position = 0.123f; 

De tal manera que lo que he instancia es una variable de tipo T, con el identificador t (donde t se pasa en el programador, es decir Position, así que tenemos una T llamados Position o se trata de estirar el concepto de meta-programación de la plantilla un poco demasiado lejos: p

+0

1. Propagación no es posible. 2. Propagablemente una idea muy rota. 3. ¿Por qué crees que necesitas esto? (4. El preprocesador puede hacer esto, pero esa no es una respuesta aceptable) – delnan

+1

Déjame adivinar: porque él es el programador de PHP anterior ;-) –

+0

Sí, sé que es oscuro! Estoy implementando un tipo de vértice con plantilla genérico, donde cada componente de un vértice tiene un tipo (es decir, flotante [3] o Vector3d, y un uso, es decir, uso_normal, uso_posición, etc. Me gustaría poder construir vértices pasando los argumentos de la plantilla y usando la recursión de la plantilla para construir una estructura, de forma similar a esto: http://www.entropygames.net/index.php?option=com_content&view=article&id=51:generic-vertices&catid=37:articles&Itemid = 56 – Robinson

Respuesta

5

No, no se puede lograr esto con las plantillas. Los nombres de las variables (conocidos como "identificadores") no pueden ser manipulados programáticamente por plantillas.Sólo el preprocessor puede hacerlo.

De todos modos, esto parece una mala idea. ¿Por qué usted quiere para hacer esto?

+0

Ok, como sospechaba :(. Gracias Charles. – Robinson

6

No, no con esa sintaxis, pero puede crear una configuración similar a lo que estás tratando de hacer:

template < typename Field > 
struct field_value 
{ 
    typename Field::type value; 
}; 

template < typename Seq > 
struct funky_struct : boost::mpl::inherit_linearly 
    < 
    Seq 
    , boost::mpl::inherit 
    < 
     field_value< boost::mpl::placeholders::_2> 
    , boost::mpl::placeholders::_1 
    > 
    >::type 
{}; 

template < typename Field, typename Struct > 
typename Field::type & get(Struct & s) { return static_cast< field_value<Field>& >(s).value; } 

struct first_field { typedef int type; }; 
struct second_field { typedef char type; }; 

struct my_funky : funky_struct< boost::mpl::vector<first_field,second_field> > {}; 

... 
my_funky f; 
get<first_field>(f) = 23; 

dejo lo que permite la construcción no predeterminado en su caso. Además, con una pequeña cantidad de trabajo, esto puede reflejarse y puede incluir cualquier cantidad de información útil sobre los campos dentro de.

+0

+1 Hago algo similar en una clase que escribí que enumera los campos de mensajes entrantes –

5

Algo como lo que quiere lograr se puede lograr con la herencia. Es decir, la clase principal tiene el nombre de la variable que desea que tenga su plantilla.

struct ItemNull {}; 

template <typename X, typename Y = ItemNull> 
class Item : public X, public Y {}; 

template <typename T> struct HasPosition { T Position; }; 
template <typename T> struct HasMomentum { T Momentum; }; 

Item< HasPosition<float> > myItem1; 
myItem1.Position = 0.123f; 

Item< HasPosition<float>, HasMomentum<float> > myItem2; 
myItem2.Position = 0.1f; 
myItem2.Momentum = 0.2f; 

El segundo argumento opcional permite para la composición, como se ilustra en myItem2. Para añadir un tercer campo, habría que agregar a la cola, o expandir desde el frente:

template <typename T> struct HasName { T Name; }; 

Item < 
    HasPosition<float>, 
    Item< HasMomentum<float>, HasName<std::string> > 
> myItem3; 
myItem3.Position = 0.1f; 
myItem3.Momentum = 0.2f; 
myItem3.Name = "Adam"; 

Item < 
    Item < HasPosition<float>, HasMomentum<float> >, 
    HasName<std::string> 
> myItem4; 
myItem4.Position = 0.1f; 
myItem4.Momentum = 0.2f; 
myItem4.Name = "Adam"; 

Mi preferencia personal es para el primero de los dos métodos, porque me parece que es una forma más intuitiva para ampliar más allá de 3 campos. La sintaxis de la plantilla Item probablemente podría simplificarse utilizando argumentos de plantilla variadic.

Las plantillas Has... podrían generarse en máquina o podría crearse una macro para que agregar nuevos campos sea una tarea relativamente simple.

#define MAKE_HAS(X) template <typename T> struct Has##X { T X; } 

MAKE_HAS(Position); 
MAKE_HAS(Momentum); 
MAKE_HAS(Name); 
Cuestiones relacionadas