c++ - 模板特化/初始化和命名空间?

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

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 上测试的,到目前为止看起来有点像错误...)

最佳答案

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

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

当该行开始时,您位于全局命名空间中。因此,g::N必须是合格的,因为 g::F<float> .

然而,当您超过您专精的事物时(即在 n_s 之后),您现在处于您专精的事物的范围内,即在 g::F 内.所有进一步查找都在此范围内完成,因此 x必须限定为 h::X .

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

全局命名空间包含F , 所以没关系,因为 g . h不附F ,但是,hg 内, 所以特化在 g 内也,从技术上讲这很好。然而,根据这个推理,您可以绝对在任何地方特化一个模板,因为您总是在包含所有内容的全局 namespace 中。所以我很确定 GCC 在这里的行为过于宽容,而且是一个错误。您也应该尝试使用其他编译器进行此操作,然后提交错误,或者可能是针对标准的缺陷报告。

关于c++ - 模板特化/初始化和命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21041369/

相关文章:

c++ - 如何确定 C++ 对象是否为 time_t

c++ - C/C++ 中有什么方法可以检测代码是否在静态初始化期间运行?

java - 静态初始化程序的合法用途?

C++ 常量预处理器宏和模板

没有 void_t 的 C++ 检测习惯用法

c++ - 模板类特化

c++ - 为什么 C++ 实例化一个被完全特化掩盖的基本模板函数?

javascript - haxe未初始化成员变量跨平台不一致

c++ - 鼠标离开控件时的 Windows 消息?

C++ 检查语句是否可以评估 constexpr