好的,这是代码:
#include <sstream>
struct A {
class Type {};
template < typename Type >
Type as( void ) {
std::istringstream test;
Type temp;
test >> temp;
return temp;
}
};
编译很好,完全没问题。
现在,几乎是相同的代码:
#include <sstream>
struct A {
class Type {};
template < typename Type >
inline Type as(void);
};
template < typename Type >
Type A::as( void ) {
std::istringstream test;
Type temp;
test >> temp;
return temp;
}
Boom,它不再编译了。错误:
t.cc:14:10: error: invalid operands to binary expression ('std::istringstream' (aka 'basic_istringstream<char>') and 'A::Type')
test >> temp;
~~~~ ^ ~~~~
我用clang和gcc重现了这种行为。
为什么编译器在第二种情况下使用了错误的类型? (只是要明确:我知道枚举存在冲突,但根据我的理解,如果真正的问题,第一个代码也应该无法编译)
答案 0 :(得分:3)
A :: as()中的范围使用A :: Type作为temp的类型限定符。最简单的方法是将嵌套类名更改为除Type之外的其他内容。
更好的问题是为什么它首先发生。它与声明点,名称查找和名称隐藏有关,所有这些都在标准的3.3,3.4和14.6.4节中介绍。这是一个非常多肉的部分,如果/当我有时间缩小它时,我会发布与这个问题相关的特定条款。到目前为止,我依靠3.3.9-10和3.4
无论如何,改变类名允许模板参数一旦超出struct 声明的范围就解决了,后者是它首先发生的关键(所以我导致无论如何都要相信标准。
struct A
{
class TypeX {};
template < typename Type >
Type as(void);
};
template < typename Type >
inline Type A::as( void )
{
std::istringstream test;
Type temp;
test >> temp;
return temp;
}
我非常有信心,如果我有与此问题相关的标准的错误部分,那么StackOverflow的充足占用者将通过此答案发送热棒。