为什么'外部内联'模板不能编译?

时间:2012-11-17 06:15:05

标签: c++ gcc clang

好的,这是代码:

#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重现了这种行为。

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

1 个答案:

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