2010-12-14 10 views
5

Gibt es eine Möglichkeit, den Namen einer Variablen innerhalb einer Klasse basierend auf einem template Argument zu generieren?Variablenname aus Vorlagenargument?

template<class T, (someconstruct) t> 

class Item { 
    public:   
     T t; 
}; 

Item<float, "Position"> myItem; 

myItem.Position = 0.123f; 

Solche dass das, was ich instanziiert haben, ist eine Variable vom Typ T, mit der Kennung t (wo t wird vom Programmierer übergeben, dh Position, also haben wir ein TPosition genannt? Oder dehnt dies die Template-Metaprogrammierkonzept ein wenig zu weit?: p

+0

1. Voraussichtlich nicht möglich. 2. Wahrscheinlich eine sehr kaputte Idee. 3. Warum denkst du, dass du das brauchst? (4. Der Präprozessor kann das, aber das ist keine akzeptable Antwort) – delnan

+1

Lass mich raten: weil er früher PHP-Programmierer ist ;-) –

+0

Ja, ich weiß, dass es obskur ist! Ich implementiere einen generischen Template-Vertex-Typ, wobei jede Komponente eines Vertex sowohl einen Typ (zB float [3] oder Vector3d - und eine Verwendung, dh usage_normal, usage_position usw. hat.) Ich möchte in der Lage sein, Vertices zu konstruieren durch Übergeben von Vorlagenargumenten und Verwenden der Vorlagenrekursion zum Erstellen einer Struktur auf ähnliche Weise: http://www.entropygames.net/index.php?option=com_content&view=article&id=51:generic-vertices&catid=37:articles&Itemid = 56 – Robinson

Antwort

5

Nein, das kann man nicht mit Templates erreichen Variablennamen (so genannte "Identifiers") können nicht programmatisch mit Templates manipuliert werden, nur die preprocessor kann das.

Egal, das scheint eine schlechte Idee zu sein. Warum möchten Sie dies tun?

+0

Ok, wie ich vermutete :(. Danke Charles. – Robinson

6

Nein, nicht mit dieser Syntax, aber Sie können eine Setup ähnlich erstellen, was Sie versuchen zu tun:

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; 

ich Ihnen ermöglicht Nicht-Standard-Bau verlassen. Auch mit einer kleinen Menge an Arbeit kann dies reflektiert werden und Sie können eine beliebige Menge an nützlichen Informationen über Felder darin stecken.

+0

+1 Ich mache etwas ähnliches in einer Klasse, die ich schrieb, die eingehende Nachrichtenfelder aufzählt –

5

Etwas, was Sie erreichen wollen, kann mit Vererbung erreicht werden. Das heißt, die Elternklasse hat den Variablennamen, den Ihre Vorlage haben soll.

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; 

Das optionale zweite Argument ermöglicht die Zusammensetzung, wie in myItem2 dargestellt. Um ein drittes Feld hinzufügen, könnten Sie an den Schwanz hinzufügen oder erweitern von vorne:

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

Meine persönlichen Präferenz ist für die ehemaligen der beiden Methoden, weil ich es als eine intuitive Art und Weise finden zu erweitern es über 3 Felder hinaus. Die Vorlagensyntax Item könnte wahrscheinlich mithilfe variadischer Vorlagenargumente vereinfacht werden.

Die Vorlagen Has... könnten maschinengeneriert sein, oder es könnte ein Makro erstellt werden, um das Hinzufügen neuer Felder zu einer relativ einfachen Aufgabe zu machen.

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

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