Имя переменной из аргумента шаблона? - PullRequest
5 голосов
/ 15 декабря 2010

Есть ли способ сгенерировать имя переменной внутри класса на основе аргумента template?

template<class T, (someconstruct) t>

class Item {
    public:        
        T t;
};

Item<float, "Position"> myItem;

myItem.Position = 0.123f;

Так, что я создал экземпляр переменной типа T, сидентификатор t (где t передается программистом, то есть Position, поэтому у нас есть T, называемый Position? Или это расширяет концепцию метапрограммирования шаблона слишком далеко?:р

Ответы [ 3 ]

6 голосов
/ 15 декабря 2010

Нет, не с этим синтаксисом, но вы МОЖЕТЕ создать настройку, аналогичную той, которую вы пытаетесь сделать:

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;

Я оставляю вам возможность строительства не по умолчанию. Кроме того, с небольшим объемом работы это может быть отражено, и вы можете вставить любое количество полезной информации о полях в пределах.

5 голосов
/ 02 июня 2012

То, что вы хотите достичь, может быть достигнуто с помощью наследования. То есть родительский класс имеет имя переменной, которую вы хотите, чтобы ваш шаблон имел.

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;

Необязательный второй аргумент учитывает композицию, как показано в myItem2. Чтобы добавить третье поле, вы можете добавить к хвосту или развернуть спереди:

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

Мое личное предпочтение отдается первому из двух методов, потому что я считаю, что это более интуитивный способ расширить его за пределы 3 полей. Синтаксис шаблона Item, вероятно, можно упростить, используя аргументы шаблона с переменным числом аргументов.

Шаблоны Has... могут быть сгенерированы машиной или могут быть созданы макросы, чтобы сделать добавление новых полей относительно простой задачей.

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

MAKE_HAS(Position);
MAKE_HAS(Momentum);
MAKE_HAS(Name);
5 голосов
/ 15 декабря 2010

Нет, вы не можете достичь этого с помощью шаблонов.Имена переменных (известные как «идентификаторы») не могут программно управляться шаблонами.Это может сделать только препроцессор .

Несмотря на это, это кажется плохой идеей.Почему вы хотите сделать это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...