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

时间:2015-01-21 15:39:48

标签: c++ templates c++11 g++ clang++

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

namespace foo
{
   template <int>
   void function();
}

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

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

template <>
void foo::function<0>()
{
}

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

  

在不同的命名空间[-fpermissive]

中的'template void foo :: function()'的特化

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

g ++也接受以下内容:

namespace foo
{
   template <>
   void function<0>()
   {
   }
}

谁是对的,gcc还是clang?

1 个答案:

答案 0 :(得分:8)

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

  

应在包含专用模板的命名空间中声明显式特化。一个明确的    declarator-id 非限定的特殊化应在最近的封闭命名空间中声明   模板,或者,如果命名空间是内联的(7.3.1),则来自其封闭的命名空间集的任何命名空间。

您必须将template<> function<0>();放入namespace foo。但是,该规则仅适用于不合格的 declarator-id 。当您提供 qualified-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