命名空间中的函数模板特化

ste*_*fan 5 c++ templates g++ c++11 clang++

我想专门化一个功能模板.此函数在命名空间中声明:

namespace foo
{
   template <int>
   void function();
}
Run Code Online (Sandbox Code Playgroud)

(为简单起见,模板基于a int,而在我的生产代码中,它是一个enum class,但它是同一个问题.基于类型的模板也是如此)

现在我想专门针对特定值:

template <>
void foo::function<0>()
{
}
Run Code Online (Sandbox Code Playgroud)

这无法编译g++ -std=c++11(版本4.6,4.7,4.8和4.9):

'template void foo :: function()'在不同命名空间中的特殊化[-fpermissive]

clang++ -std=c++11 接受此代码.

g ++也接受以下部分:

namespace foo
{
   template <>
   void function<0>()
   {
   }
}
Run Code Online (Sandbox Code Playgroud)

谁是对的,gcc还是clang?

Bar*_*rry 8

根据标准§14.7.3/ 2,强调我的:

应在包含专用模板的命名空间中声明显式特化.一个明确的分工,其声明符-ID没有资格应在模板的最近的封闭命名空间声明,或者,如果命名空间是内联(7.3.1),从它的封闭命名空间集中的任何命名空间.

你必须把template<> function<0>();namespace foo.但是,该规则仅适用于非限定声明者标识.当你提供一个限定id(如foo::function<0>)时,我认为该条款不适用,这使得clang在这里是正确的.

例如,鉴于function声明了问题,我希望如下:

namespace foo {
    template <> void function<0>(); // valid: unqualified explicit specialization
                                    // in the nearest enclosing namespace of the 
                                    // template
}

namespace bar {
    template <> void function<1>(); // invalid: unqualified explicit specialization
                                    // in the wrong namespace
}

struct baz {
    template <> void function<2>(); // invalid: unqualified explicit specialization
                                    // not in namespace scope
};

template <> void foo::function<3>(); // valid: qualified explicit specialization
                                     // is in a namespace, and id is qualified

template <> void bar::function<4>(); // invalid: there is no bar::function
                                     // to specialize
Run Code Online (Sandbox Code Playgroud)