不完整类型的无效使用

2021-12-13 00:00:00 templates c++ typedef crtp

我试图在我的项目中使用来自子类的 typedef,我已经在下面的示例中隔离了我的问题.

I'm trying to use a typedef from a subclass in my project, I've isolated my problem in the example below.

有人知道我哪里出错了吗?

Does anyone know where I'm going wrong?

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’

推荐答案

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

The reason is that when instantiating a class template, all its declarations (not the definitions) of its member functions are instantiated too. The class template is instantiated precisely when the full definition of a specialization is required. That is the case when it is used as a base class for example, as in your case.

那么发生的事情是 A

So what happens is that A<B> is instantiated at

class B : public A<B>

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

at which point B is not a complete type yet (it is after the closing brace of the class definition). However, A<B>::action's declaration requires B to be complete, because it is crawling in the scope of it:

Subclass::mytype

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

What you need to do is delaying the instantiation to some point at which B is complete. One way of doing this is to modify the declaration of action to make it a member template.

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

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

It is still type-safe because if var is not of the right type, passing var to do_action will fail.

相关文章