基础模板类的数据成员在派生模板类中不可见?

9
考虑以下C++代码,
template <typename Derived>
struct A
{
    bool usable_;
};

template <typename Derived>
struct B : A< B<Derived> >
{
    void foo()
    {
        usable_ = false;
    }
};

struct C : B<C>
{
    void foo()
    {
        usable_ = true;
    }
};

int main()
{
    C c;
}

我遇到了编译错误:在成员函数void B<Derived>::foo()中:

template_inherit.cpp:12: 错误:'usable_'在此作用域中未声明。

为什么会出现这种情况?有什么好的解决方法吗?


3
"B 结构体继承自 A<B<Derived>>。" - GManNickG
3
@GMan 哈哈,CRTP 伪装起来了 :) (意思是在某种情况下,使用了 CRTP (Curiously Recurring Template Pattern)这个技术,但并没有直接明示或者提到它,所以说是“伪装”起来了。) - Johannes Schaub - litb
1个回答

17

那是因为usable_是一个非依赖名称,所以它在解析模板时进行查找,而不是在实例化(即已知基类时)进行查找。

未限定名称查找不会查找依赖于基类的任何非依赖名称。您可以按照以下方式使名称usable_成为依赖项,这也将消除未限定名称查找:

this->usable_ = false;

// equivalent to: A<B>::usable_ = false;
A< B<Derived> >::usable_ = false;

B::usable_ = false;

所有这些都可以使用。或者你可以在派生类中使用 using-declaration 声明名称。

template <typename Derived>
struct B : A< B<Derived> >
{
    using A< B<Derived> >::usable_;

    void foo()
    {
        usable_ = false;
    }
};

注意,在C中不会有问题——它只影响B


最后一篇 GotW 谈到了这个问题。可惜的是,Herb Sutter通常写得很好的解决方案没有出现。:( - wilhelmtell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接