如何推断CRTP中的类型?

时间:2016-07-07 09:18:55

标签: c++ templates inheritance crtp

我想在c ++模板中实现CRTP。代码如下:

template <typename T>
class A{
public:
    typedef typename T::Scalar Scalar;
};
template <typename T>
struct B:public A<B<T> > {
public:
    typedef T Scalar;
};

但是当我compile the code编译器显示:

error: no type named ‘Scalar’ in ‘struct B<int>’

有人可以解释一下吗?

3 个答案:

答案 0 :(得分:0)

问题在于A<T>的API表示必须定义T::Scalartemplate<typename U> struct B:public A<B<U> > {中的情况并非如此。

简单的改变是修复A的API:

template <typename SCALAR>
class A{
public:
    typedef SCALAR Scalar;
};
template <typename T>
struct B:public A<T> {
};

在抽象术语中,A<T>, T::Scalar的使用是一种名称传递形式,而A<SCALAR>是常规的逐个传递。当名称尚未在您需要的位置定义时,按名称传递是有问题的。

[编辑] 而且因为它似乎不明显,你仍然可以保留CRTP:

template <typename SCALAR, typename CRTP>
class A{
public:
    typedef SCALAR Scalar;
};
template <typename T>
struct B:public A<T, B<T>> {
};

答案 1 :(得分:0)

错误是由于类型不完整造成的。看下面一行:

template<typename T>
struct B : public A<B<T>> 

B<T>的正文尚未启动,您将其用作构建A<T>的参数。实际上这是允许的,但如Quentin's answer中所述,它是CRTP的一个警告。除了答案,这是另一种方式:

template <template<typename> class Base, typename T>
class A{ // use `<typename...>` for C++11
public:  
  typedef T Scalar;
  // use `Base<T>` wherever required
};

template <typename T>
struct B : public A<B, T> {
public: //        ^^^^^^^
    typedef T Scalar;
};

答案 2 :(得分:0)

另一种看待它的方式,

B<int> b is called which will invoke
B<int> : A<B<int> > which will further invoke // B is not yet done waiting on A<B<int> >

A<B<int>> { typedef B<int>::Scalar Scalar } will try to fetch B<int> //which is not yet constructed as many pointed out.

下面的代码不是解决方案,但会解释什么是问题。下面的代码编译,因为我们打破了循环。

template <typename T>
class A{
public:
    typedef typename T::Scalar Scalar;
};

template <typename T>
class B:public A<B<T> > {
public:
    typedef T Scalar;
};

template <>
class A<B<int> > {
public :
        typedef int Scalar;
};

int main()
{
        B<int> b;
}

现在解决方案是打破循环或避免循环。我们可以相应地考虑一些解决方案。