2015-10-20 61 views
6

下面的代码不编译,除非注释行是未注释: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和相关的类和指向类的指针的名称空间包含类本身,因此编译器希望该类是完整的。也许。

int main() 
{ 
    // A<int>(); // Works if uncommented. 

    auto& x = R<A<int>*>::r(); 
    B<int>(); 
} 

我要去这里走出去的肢体,并说,这是因为你暗示:

+0

有啥你的问题? –

+0

为什么不编译?为什么编译器希望'A '在查看'operator(B :: V,A *)'时是完整的?为什么它在注释行被取消注释时工作? –

+3

编译器输出的错误是什么意思? –

回答

0

如果你改变主要是这一点,你得到同样的错误消息。提到一个指向A<int>的指针不会导致A<int>的模板扩展。

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

也许有人比我更聪明可以在标准中找到要求这一点的段落。

0

我现在还不明白为什么enum hack在这里不起作用。 但这似乎工作:

static const int v = sizeof(M::m((R<V>::r(), R<A<T>*>::r()))); 

它编译使用gcc-4.8.4,但无法与铛-3.6编译。 错误与以前相同。

下编译既:

template <class T> 
struct B { 
    struct U { }; 
    struct V { M& operator,(U); }; 
    static const int v; 
}; 

template <class T> 
const int B<T>::v = sizeof(M::m((R<V>::r(), R<A<T>*>::r())));