无效的使用不完整的types

我想在我的项目中使用一个子类的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; } 

这是我得到的输出:

 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' 

原因是当实例化一个类模板时,它的所有成员函数的声明(而不是定义)也被实例化了。 类模板被精确地实例化,当需要专门化的完整定义时。 例如,当它用作基类时就是这种情况,就像你的情况一样。

那么会发生什么是A<B>被实例化在

 class B : public A<B> 

此时B还不是一个完整的types(它是在类定义的右括号之后)。 然而, A<B>::action的声明要求B是完整的,因为它在它的范围内进行爬取:

 Subclass::mytype 

你需要做的是将实例化延迟到B完成的某个点。 这样做的一种方法是修改action声明使其成为成员模板。

 template<typename T> void action(T var) { (static_cast<Subclass*>(this))->do_action(var); } 

它仍然是types安全的,因为如果var不是正确的types,将var传递给do_action将会失败。

你可以通过使用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; } 

你从A<B>派生B ,所以一旦它看到B类的定义,编译器首先要尝试实例化A<B> 。 要做到这一点,它需要知道B::mytypeaction参数。 但是由于编译器只是在计算B的实际定义的过程中,它还不知道这种types,所以会出现错误。

解决这个问题的方法之一是将参数types声明为另一个模板参数,而不是在派生类中:

 template<typename Subclass, typename Param> class A { public: void action(Param var) { (static_cast<Subclass*>(this))->do_action(var); } }; class B : public A<B, int> { ... }; 

不完全是你问的,但你可以使行动模板成员函数:

 template<typename Subclass> class A { public: //Why doesn't it like this? template<class V> void action(V var) { (static_cast<Subclass*>(this))->do_action(); } }; 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; } 

您需要使用指针或引用,因为此时不知道正确的types,编译器不能实例化它。

请尝试:

 void action(const typename Subclass::mytype &var) { (static_cast<Subclass*>(this))->do_action(); }