我想在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>’
有人可以解释一下吗?
答案 0 :(得分:0)
问题在于A<T>
的API表示必须定义T::Scalar
,template<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;
}
现在解决方案是打破循环或避免循环。我们可以相应地考虑一些解决方案。