4

好的,这是一个代码:

#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;
}

砰,它不再编译了。错误 :

t.cc:14:10: error: invalid operands to binary expression ('std::istringstream' (aka 'basic_istringstream<char>') and 'A::Type')
    test >> temp;
    ~~~~ ^  ~~~~

我已经用 clang 和 gcc 重现了这种行为。

为什么编译器在第二种情况下使用错误的类型?(只是要清楚:我知道与枚举存在冲突,但据我了解,如果是真正的问题,第一个代码也应该无法编译)

4

1 回答 1

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的大量占用者将通过此答案发送热棒。

于 2012-11-17T07:40:03.717 回答