下面的代码不能编译,除非注释行没有被注释:
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>
的模板展开。
这是有意义的(对我来说),因为它和提到一个指向前向声明类型的指针是一样的——你不需要在那一点上完全定义类型。
也许比我更聪明的人能在标准中找到要求这样做的段落。