[英]invalid use of incomplete type
我正在尝试在我的项目中使用来自子类的 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;
}
这是我得到的 output:
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’
原因是当实例化一个 class 模板时,它的所有成员函数的声明(不是定义)也被实例化了。 class 模板在需要专业化的完整定义时精确实例化。 例如,当它用作基础 class 时就是这种情况,就像您的情况一样。
所以发生的事情是A<B>
被实例化在
class B : public A<B>
此时B
还不是一个完整的类型(它位于 class 定义的右大括号之后)。 但是, A<B>::action
的声明要求B
是完整的,因为它在它的 scope 中爬行:
Subclass::mytype
您需要做的是将实例化延迟到B
完成的某个点。 这样做的一种方法是修改action
声明以使其成为成员模板。
template<typename T>
void action(T var) {
(static_cast<Subclass*>(this))->do_action(var);
}
它仍然是类型安全的,因为如果var
不是正确的类型,则将var
传递给do_action
将失败。
您可以通过使用特征 class 来解决此问题:
它要求您为您使用的每个实际 class 设置一个特殊的特征 class。
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
,因此编译器一旦看到 class B
的定义,首先要做的就是尝试实例化A<B>
。 为此,它需要知道B::mytype
的参数action
。 但是由于编译器只是在弄清楚B
的实际定义的过程中,它还不知道这个类型,你会得到一个错误。
解决此问题的一种方法是将参数类型声明为另一个模板参数,而不是在派生的 class 中:
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> { ... };
不完全是您所要求的,但您可以对模板成员 function 执行操作:
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;
}
您需要使用指针或引用,因为此时不知道正确的类型,编译器无法实例化它。
而是尝试:
void action(const typename Subclass::mytype &var) {
(static_cast<Subclass*>(this))->do_action();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.