C++运算符逗号/转发参考代码无法编译



下面的代码不能编译,除非注释行没有被注释:

template <class T> struct R { static T& r(); };
struct M {
    static char m(M&);
    template <class T> static int m(const T&);
};
template <class T> struct A;
template <class T>
struct B {
    struct U { };
    struct V { M& operator,(U); };
    enum { v = sizeof(M::m((R<V>::r(), R<A<T>*>::r()))) };
};
template <class T> struct A { B<T> y; };
int main()
{
//  A<int>();  // Works if uncommented.
    B<int>();
}

在逗号操作符处,编译器认为它需要A<int>是完整的,即使代码只在A<T>*中传输。我不明白为什么。它在clang和g++中都失败了。铿锵声说

h.cpp:13:36: error: field has incomplete type 'B<int>'
template <class T> struct A { B<T> y; };
                                   ^
h.cpp:11:38: note: in instantiation of template class 'A<int>' requested here
    enum { v = sizeof(M::m((R<V>::r(), R<A<T>*>::r()))) };
                                     ^
h.cpp:17:5: note: in instantiation of template class 'B<int>' requested here
    B<int>();
    ^
h.cpp:8:8: note: definition of 'B<int>' is not complete until the closing '}'
struct B {
       ^
1 error generated.

我现在坐在调试器调试编译器:-)我认为发生的事情是编译器正在使用参数依赖的查找来找到匹配的operator, s和相关的类和命名空间的指针指向一个类包括类本身,所以编译器希望类是完整的。也许。

如果您将main更改为如下,则会得到相同的错误信息:

int main()
{
    // A<int>();  // Works if uncommented.
    auto& x = R<A<int>*>::r();
    B<int>();
}

我要冒险一下,就像你暗示的那样。提到指向A<int>的指针不会导致A<int>的模板展开。

这是有意义的(对我来说),因为它和提到一个指向前向声明类型的指针是一样的——你不需要在那一点上完全定义类型。

也许比我更聪明的人能在标准中找到要求这样做的段落。

最新更新