sea*_*ges 53 c++ templates typedef crtp
我正在尝试在项目中使用子类的typedef,我在下面的示例中已经分离了我的问题.
有谁知道我哪里出错了?
template<typename Subclass>
class A {
public:
//Why doesn't it like this?
void action(typename Subclass::mytype var) {
(static_cast<Subclass*>(this))->do_action(var);
}
};
class B : public A<B> {
public:
typedef int mytype;
B() {}
void do_action(mytype var) {
// Do stuff
}
};
int main(int argc, char** argv) {
B myInstance;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
sean@SEAN-PC:~/Documents/LucadeStudios/experiments$ g++ -o test test.cpp
test.cpp: In instantiation of ‘A<B>’:
test.cpp:10: instantiated from here
test.cpp:5: error: invalid use of incomplete type ‘class B’
test.cpp:10: error: forward declaration of ‘class B’
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 63
原因是,在实例化类模板时,其成员函数的所有声明(而不是定义)也会被实例化.当需要完整定义特化时,将精确地实例化类模板.例如,在它被用作基类时就是这种情况,就像你的情况一样.
所以会发生什么A<B>是实例化的
class B : public A<B>
Run Code Online (Sandbox Code Playgroud)
此时B还不是一个完整的类型(它是在类定义的结束括号之后).但是,A<B>::action声明需要B完整,因为它在它的范围内爬行:
Subclass::mytype
Run Code Online (Sandbox Code Playgroud)
您需要做的是将实例化延迟到B完成的某个点.这样做的一种方法是修改声明action以使其成为成员模板.
template<typename T>
void action(T var) {
(static_cast<Subclass*>(this))->do_action(var);
}
Run Code Online (Sandbox Code Playgroud)
它仍然是类型安全的,因为如果var是不正确的类型,传递var到do_action将失败.
Mar*_*ork 24
你可以通过使用traits类来解决这个问题:
它要求你为你使用的每个实际类设置一个特殊的traits类.
template<typename SubClass>
class SubClass_traits
{};
template<typename Subclass>
class A {
public:
void action(typename SubClass_traits<Subclass>::mytype var)
{
(static_cast<Subclass*>(this))->do_action(var);
}
};
// Definitions for B
class B; // Forward declare
template<> // Define traits for B. So other classes can use it.
class SubClass_traits<B>
{
public:
typedef int mytype;
};
// Define B
class B : public A<B>
{
// Define mytype in terms of the traits type.
typedef SubClass_traits<B>::mytype mytype;
public:
B() {}
void do_action(mytype var) {
// Do stuff
}
};
int main(int argc, char** argv)
{
B myInstance;
return 0;
}
Run Code Online (Sandbox Code Playgroud)