有没有办法根据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
答案 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);