使用CRTP时,在基类中使用非模板派生类的typedef

时间:2014-09-04 09:26:37

标签: c++ templates crtp

我使用CRT模式并希望基类从派生类中查看typedef s。在this post @James McNellis建议使用base_traits类来做到这一点,并且它工作正常。但是在该帖子中描述的情况下,派生类本身就是一个模板。当派生类不是模板时,此方法在VS2010中不起作用。

template <class D>
struct base_traits;
template <class D>
struct base
{
    typedef typename base_traits<D>::value_t value_t;
};

struct derived : base<derived>
{
    typedef typename base_traits<derived>::value_t value_t;
};

template<>
struct base_traits<derived>
{
    typedef int value_t;
};

上面的代码提供了很多错误。第一个是:

  

错误C2027:使用未定义类型&#39; base_traits

base类的typedef。

的行上

2 个答案:

答案 0 :(得分:6)

base_traits<derived>必须在使用之前声明和定义,因为base<derived>的隐式实例需要它(下面,我转发声明derived):

template <class D>
struct base_traits;


template <class D>
struct base
{
    typedef typename base_traits<D>::value_t value_t;
};

struct derived;

template<>
struct base_traits<derived>
{
    typedef int value_t;
};

struct derived : base<derived>
{
    typedef base_traits<derived>::value_t value_t;
};


int main(void)
{
    derived d;
}

Live demo

答案 1 :(得分:4)

§14.7.3[temp.expl.spec] / p7:

  

为函数放置显式特化声明   模板,类模板,变量模板,成员函数   类模板,类模板的静态数据成员,成员   类模板类,类模板的成员枚举,   类模板的成员类模板,成员函数模板   类模板,类模板的静态数据成员模板,   类模板的成员模板的成员函数,成员   非模板类的成员模板的功能,静态数据   非模板类的成员模板,成员函数模板   类模板的成员类等,以及部分的放置   类模板的特化声明,变量模板,   非模板类的成员类模板,静态数据成员   非模板类的模板,类的成员类模板   模板等可以影响程序是否格式正确   到显式专业化的相对定位   声明及其在翻译单元中的实例化要点   如上下文所述。 撰写专业时,请   小心它的位置;或者使它编译将是这样的试验   点燃自焚。

特别是(§14.7.3[temp.expl.spec] / p6),

  

如果模板[...]明确专门化,那么该专业化   应在首次使用该专业化之前申报   会导致在每一个中发生隐式实例化   发生这种用途的翻译单位;没有诊断   需要。如果程序没有提供定义   显式专业化和专业化以某种方式使用   这将导致隐式实例化[...],   该计划格式错误,无需诊断。

必须在base_traits<derived>的定义之前声明和定义显式特化derived,否则继承自base<derived>和使用base_traits<derived>::value_t将触发隐式实例化。因此:

template <class D>
struct base_traits;

template <class D>
struct base
{
    typedef typename base_traits<D>::value_t value_t;
};

struct derived;

template<>
struct base_traits<derived>
{
    typedef int value_t;
};

struct derived : base<derived>
{
    typedef base_traits<derived>::value_t value_t;
};