【问题标题】:Visibility problems when using CRTP使用 CRTP 时的可见性问题
【发布时间】:2016-08-03 07:49:46
【问题描述】:

这是我能想到的一个小例子:

template <typename T>
struct Util
{
    using Type = int;
};

struct A
{
    struct B : public Util<B> {
        void fun(Type) {}
    };
};

template <typename T>
struct C
{
    struct D : public Util<D> {
        void fun(Type) {}
    };
};

int main()
{
    A::B{}.fun(0);
    C<int>::D{}.fun(0);
}

A::BC::D 之间的唯一区别是 C 是一个模板。

Struct C::D 编译失败,出现以下错误:

test_cpp.cpp:18:18: error: ‘Type’ has not been declared
         void fun(Type) {}
                  ^~~~

为什么编译失败?如何编译?

假设 Util 来自外部库,我无法更改它(如果你有兴趣,它是 boost::iterator_facade)。

【问题讨论】:

    标签: c++11 crtp


    【解决方案1】:

    此时:

    template <typename T>
    struct C
    {
        struct D : public Util<D> {
            void fun(Type) {} // <-- here
        };
    };
    

    编译器无法知道 * Type 需要来自Util&lt;D&gt; 的范围。调用基类成员函数也是同样的问题,需要用this-&gt;显式限定,否则找不到。

    您应该能够通过明确限定类型来解决此问题:

    void fun(typename Util<D>::Type) {}
    

    complete snippet on Coliru

    差异背后的原因是,正如@etam1024 在评论中正确指出的那样,在A::B 中,Type 是一个非依赖名称,而在C::D 中它是一个依赖名称。有关基类成员函数this answer的成员函数限定的类似情况的解释,请参阅。

    * 在我看来,编译器可以知道在哪里寻找Type,但是语言规则说它看起来并不那么远。请注意,我可能会忽略编译器无法推断出这一点的特殊情况,因此导致需要完全考拉的一般情况。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    相关资源
    最近更新 更多