我有一个宏,用于使用继承构造函数对模板进行自动子类型化,如下所示:
#define INST_TMPL(NAME,TMPL,...) \
struct NAME : public TMPL<__VA_ARGS__> { \
typedef TMPL<__VA_ARGS__> Base;\
using Base::Base;\ // Inherit constructors
};
请不要争论这样的宏是否必要或良好的风格。对我们的项目很有帮助;我们用它来缩短很长模板的类型名称。例如,我们可以缩短模板的名称 LongName<int,float,x::y::LongInnerType>
通过使用INST_TMPL(MyType,LongName,int,float,x::y::LongInnerType)
。现在我们可以简单地使用MyType
而不是长模板,并且类型也将显示在错误消息中(而不是扩展的模板名称)。
但是现在有一个问题:根据所使用的模板,我们有时需要一个 typename
在 typedef
宏里面。例如,如果使用的模板是模板参数 T
的内部模板,例如T::LongName<...>
,那么我们需要 typename
在 typedef 中,即:
typedef typename TMPL<__VA_ARGS__> Base;\
当然,我可以创建两个宏,其中一个带有 typename
和一个没有。然而,这相当麻烦。相反,我希望有一个对于这两种情况都能正确编译的宏。这可能吗?
最佳答案
来自评论:
一种重写此方法的方法,其中 typename
可以通过宏参数指定的方法是使用一个简单地报告其自己的模板参数的辅助模板类。
template <typename T>
struct id { typedef T type; };
#define INST_TMPL(NAME,...) \
struct NAME : id<__VA_ARGS__>::type { \
typedef typename id<__VA_ARGS__>::type Base; \
using Base::Base; \
};
像INST_IMPL(MyType,LongName<int,float,x::y::LongInnerType>)
一样使用它,或者像 INST_IMPL(MyType,typename T::LongName<int,float,x::y::LongInnerType>)
.
使用typename id<...>::type
即使这是非依赖类型也是允许的。
关于必要时插入类型名的 C++ 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26233807/