2010-12-14 89 views
5

Existe-t-il un moyen de générer le nom d'une variable dans une classe basée sur un argument template?Nom de la variable de l'argument du modèle?

template<class T, (someconstruct) t> 

class Item { 
    public:   
     T t; 
}; 

Item<float, "Position"> myItem; 

myItem.Position = 0.123f; 

tel que ce que j'instancié est une variable de type T, avec l'identifiant t (où t est transmise par le programmeur, soit Position, nous avons donc un T appelé Position? Ou est-ce l'étirement de la modèle de méta-programmation de modèle un peu trop loin?: p

+0

1. Propablement pas possible. 2. Propably une idée très brisée. 3. Pourquoi pensez-vous que vous en avez besoin? (4. Le préprocesseur peut le faire, mais ce n'est pas une réponse acceptable) – delnan

+1

Laisse-moi deviner: parce qu'il est un ancien programmeur PHP ;-) –

+0

Oui, je sais que c'est obscur! J'implémente un type de vertex générique basé sur un template, où chaque composant d'un vertex possède à la fois un type (float [3] ou Vector3d) et un usage, ie usage_normal, usage_position, etc. J'aimerais pouvoir construire des sommets en transmettant des arguments de modèle et en utilisant la récursivité modèle pour construire une structure, de la même manière: http://www.entropygames.net/index.php?option=com_content&view=article&id=51:generic-vertices&catid=37:articles&Itemid = 56 – Robinson

Répondre

5

Non, vous ne pouvez pas réaliser cela avec des modèles.Les noms de variables (connus sous le nom «identificateurs») ne peuvent pas être manipulés par des modèles par programmation.C'est le preprocessor qui peut le faire.

Peu importe, cela semble être une mauvaise idée. Pourquoi voulez-vous voulez pour ce faire?

+0

Ok, comme je le soupçonnais :(Merci Charles – Robinson

6

Non, pas avec cette syntaxe, mais vous pouvez créer une configuration similaire à ce que vous essayez de faire:

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; 

Je laisse en permettant la construction non par défaut pour vous. En outre, avec une quantité mineure de travail cela peut être reflété et vous pouvez coller toute quantité d'informations utiles sur les champs à l'intérieur.

+0

+1 Je fais quelque chose de similaire dans une classe que j'ai écrit qui énumère les champs de message entrant –

5

Quelque chose comme ce que vous voulez réaliser peut être accompli avec l'héritage. Autrement dit, la classe parente a le nom de la variable que vous voulez que votre modèle ait.

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; 

Le second argument optionnel permet une composition, comme illustré sur myItem2. Pour ajouter un troisième champ, vous pouvez ajouter à la queue, ou d'étendre à l'avant:

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"; 

Ma préférence personnelle est pour l'ex-des deux méthodes, parce que je trouve être une façon plus intuitive d'étendre au-delà de 3 champs. La syntaxe du modèle Item pourrait probablement être simplifiée en utilisant des arguments de modèle variadique. Les modèles Has... peuvent être générés par une machine ou une macro peut être créée pour rendre l'ajout de nouveaux champs une tâche relativement simple.

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

MAKE_HAS(Position); 
MAKE_HAS(Momentum); 
MAKE_HAS(Name);