【问题标题】:template specialization/initializations and namespaces?模板专业化/初始化和命名空间?
【发布时间】:2014-01-29 06:03:10
【问题描述】:

C++ 关于模板特化和命名空间限定的规则是什么?我有一些代码可以归结为以下内容,这让我意识到我不了解 C++ 关于模板专业化初始化的规则。首先我觉得很奇怪g::F<> 的专业化甚至在h 中是允许的,但鉴于此,我不知道为什么事情会这样。

namespace g {

  struct N {
    N(char c):c_(c){}
    char c_;
  };

  template <typename V>
  struct F {
    static N n_s; // <-- want to initialize these for specializations
  };

  namespace h {
    struct X { static constexpr char k{'x'}; };

    template <> N F<char>::n_s{h::X::k};  // OK
    template <> N F<int>::n_s{X::k};      // fails on "‘X’ not declared"
  }
} // namespace g

// Seems weirdest to me. N and F need full qualifications but X doesn't.
template <> g::N g::F<float>::n_s{h::X::k}; // OK also!

最后的实例化/初始化,其中模板静态成员初始化器推断 g 命名空间,使模板看起来好像初始化器在代码中与模板定义位于同一位置自己。

规定这种行为的规范规则是什么? (请注意,这是在 gcc 4.8.1 上测试的,到目前为止看起来有点像一个错误......)

【问题讨论】:

    标签: c++ template-specialization static-initialization fully-qualified-naming


    【解决方案1】:

    这里的主要混淆不是关于专业化,而是关于资格。让我们看看最后一个特化(在全局命名空间中)来说明这一点:

    template <> g::N g::F<float>::n_s{h::X::k};
    

    当行开始时,您处于全局命名空间中。因此,g::N 必然是合格的,g::F&lt;float&gt; 也是如此。

    但是,一旦您超越了您专攻的事物(即在 n_s 之后),您现在就处于您所专攻的事物的范围内,即在 g::F 内。所有进一步的查找都是在这个范围内完成的,所以x 必须限定为h::X。

    也就是说,虽然允许在包含原始命名空间的命名空间中专门化事物,但在嵌套命名空间(在您的情况下为 h)对我来说看起来很奇怪,但这里的标准有点模棱两可,正如它所说在 14.7.3/2 中:“应在包含专门模板的命名空间中声明显式专门化。”

    全局命名空间包含F,这很好,g 也是如此。 h 不包含F,但是h 在g 之内,所以专业化也在g 之内,从技术上讲这很好。但是,通过这种推理,您可以在任何地方都专门化一个模板,因为您始终位于包含所有内容的全局命名空间中。所以我很确定 GCC 在这里的行为过于宽容,而且是一个错误。您也应该使用其他编译器尝试此操作,然后提交错误,或者可能针对标准提交缺陷报告。

    【讨论】:

    • 谢谢,这与我所怀疑的一致,但我在阅读规范时找不到直接的矛盾。当我将其提炼为上面最简单的等效案例/行为时,我试图将 F 之类的模板别名为 h 之类的嵌套命名空间。
    【解决方案2】:

    在:

    template <> N F<int>::n_s{X::k};      // fails on "‘X’ not declared"
    

    它失败是因为与F&lt;int&gt;::n_s 关联的命名空间是g,而X 是在g::h 中声明的。这就是为什么您需要将其拼写为 h::F&lt;int&gt;::n_s。

    【讨论】:

    • 嗯?你的意思是像 g::F::n_s 那样拼写吗?我可以清楚地看到,无论在何处使用它,它都必须像命名空间 g 一样被限定,但我不明白为什么在 h 中允许 F::n_s 初始化或为什么 F::n_s {h::X::k} 允许在 g 之外进行初始化,而无需额外的 g:: 限定符...
    猜你喜欢
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 2013-12-04
    • 2020-12-27
    相关资源
    最近更新 更多