C++宏,必要时插入typename

C++ macro that inserts typename if necessary

本文关键字:插入 typename C++      更新时间:2023-10-16

我有一个宏,用于使用继承构造函数自动对模板进行子类型划分,如下所示:

#define INST_TMPL(NAME,TMPL,...)  
struct NAME : public TMPL<__VA_ARGS__> {    
   typedef TMPL<__VA_ARGS__> Base;
   using Base::Base; // Inherit constructors
};

请不要争论这样的宏是必要的还是好的风格。它对我们的项目很有帮助;我们使用它来缩短非常长的模板的类型名称。例如,我们可以使用INST_TMPL(MyType,LongName,int,float,x::y::LongInnerType)来缩短模板LongName<int,float,x::y::LongInnerType>的名称。现在我们可以简单地使用MyType而不是长模板,并且类型也将显示在错误消息中(而不是扩展的模板名称)。

但现在有一个问题:根据使用的模板,我们有时需要在宏内的typedef中使用typename。例如,如果使用的模板是模板参数T的内部模板,例如T::LongName<...>,那么我们需要typedef中的typename,即:

   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