【问题标题】:function template specialization in a namespace命名空间中的函数模板特化
【发布时间】:2015-01-21 15:39:48
【问题描述】:

我想专门化一个函数模板。该函数在命名空间中声明:

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)编译:

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

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

g++ 也接受以下部分:

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

谁是对的,gcc 还是 clang?

【问题讨论】:

  • 两者都是正确的。唯一的区别是 clang 有一个扩展允许这种非标准声明。
  • @Ethouris 这与 Barrys 的回答相矛盾。想指出他哪里错了吗?
  • 不,它没有,尽管您可能误解了我的回答。我说两个编译器都是对的,因为他们都说这段代码不符合标准 C++。唯一的区别是clang允许这个仍然非标准代码,但将其视为使用非标准扩展
  • 这是我对标准那部分的理解,但我绝不是这件事的权威。我只是一个在网上回答问题的人:-)
  • @Barry 当然,毫无疑问。但Ethouris 说的是另一回事。所以我想鼓励他用事实(比如引用标准)来支持他的陈述。你们中的一个(甚至两个)都错了,所以我很想知道是谁;-)

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


【解决方案1】:

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

应在包含专用模板的命名空间中声明显式特化。显式 declarator-idnotqualified 的特化应在最近的封闭命名空间中声明 模板,或者,如果命名空间是内联的 (7.3.1),则可以是其封闭命名空间集中的任何命名空间。

您必须将template&lt;&gt; function&lt;0&gt;(); 放入namespace foo。但是,该规则仅适用于不合格的 declarator-id。当您提供qualified-id(如foo::function&lt;0&gt;)时,我认为该子句不应该适用,这使得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

【讨论】:

  • 全局命名空间中包含了专门的模板,那么全局命名空间中的template&lt;&gt; void foo::function&lt;0&gt;(){}是如何打破你引用的规则的呢?
  • @PowerGamer 对于foo 命名空间,全局命名空间无论如何是“最近的封闭命名空间”?只是问-也许你是对的。该规则使用了许多非常不清楚的陈述。如果我能看到在“正确”和“错误”命名空间以及“合格”和“不合格”声明符 ID 中定义这个东西之间的区别,那就太好了。
  • @Ethouris 添加了我对规则的理解的示例。
  • @Ethouris 在function 之前没有foo:: 的例子是“declarator-id 不合格”的例子。
  • @Ethouris 您对标准规则的改写更长但正确。 specialized template 表示template is special(与specialization of the template 不同)。限定的显式特化不能在任何命名空间中定义,只能在命名空间enclosing the specialized template 中定义。在 C++11 标准的 7.3.1/6 中查找enclosing namespace 的定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多