在CRTP

时间:2015-11-20 14:11:04

标签: c++

假设我定义了一个使用模板参数T的嵌套类的模板P,如下所示:

template<class P> class T
{
public:
    T(P& p) : p(p) {}
    P& p;
    typename P::Nested& get_nested()    { return p.nested; }
};

如果我声明一个包含名为A的嵌套类的类Nested,我可以定义一个T<A>类型的变量,没有问题:

class A
{
public:
    class Nested
    {
    public:
        int i;
    };
    Nested nested;
};

void test2a()
{
    A a;
    a.nested.i = 1;
    T<A> t_a(a);
    t_a.get_nested().i = 2;
}

现在,我想声明一个类B,它以同样的方式包含一个名为Nested的嵌套类,并继承自T<B>,如下所示:

class B : public T<B>
{
public:
    class Nested
    {
    public:
        int i;
    };
    Nested nested;
};

上述代码的编译失败,错误:&#34; 嵌套不是 B &#34;

的成员

我想我理解发生了什么:在输入模板时,由于继承,B类未完全定义。

但是,我想知道是否有办法做这样的事情......

感谢您的帮助。

2 个答案:

答案 0 :(得分:6)

你需要推迟get_nested的返回类型的分辨率,直到它被调用。

一种方法是使返回类型依赖于模板参数:

  template<typename unused = void>
    typename std::conditional<false, unused, P>::type::Nested&
    get_nested()    { return p.nested; }

另一种方式(自C ++ 14起)是使用返回类型推导:

  auto& get_nested()    { return p.nested; }

答案 1 :(得分:3)

我能用简单的

编译你的例子
template<class P> class T
{
public:
    T(P& p) : p(p) {}
    P& p;
    auto& get_nested()    { return p.nested; }
};

另一种方法,利用与@ecatmur相同的技巧,但有点简单:

template<class R = P>
typename R::Nested& get_nested()    { return p.nested; }

同样,在这里,编译器必须推迟对P::Nested的评估,直到您致电get_nested()