模板参数的变量名?

时间:2010-12-14 21:29:49

标签: c++ templates generics

有没有办法根据template参数在类中生成变量的名称?

template<class T, (someconstruct) t>

class Item {
    public:        
        T t;
};

Item<float, "Position"> myItem;

myItem.Position = 0.123f;

这样我实例化的是T类型的变量,标识符为t(其中t由程序员传递,即Position,所以我们有一个名为T的{​​{1}}?或者这对模板元编程概念有点过分了?:p

3 个答案:

答案 0 :(得分:6)

不,不是那种语法,但你可以创建一个类似于你想要做的设置:

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;

我留下允许非默认构造给你。此外,只需少量工作即可反映出来,您可以在其中填写任何有用的信息。

答案 1 :(得分:5)

不,你无法通过模板实现这一目标。变量名称(称为“标识符”)不能由模板以编程方式操作。只有preprocessor可以做到这一点。

无论如何,这似乎是一个坏主意。为什么想要这样做?

答案 2 :(得分:5)

您希望实现的目标可以通过继承来完成。也就是说,父类具有您希望模板具有的变量名称。

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