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
,但是,h
在 g
内, 所以特化在 g
内也,从技术上讲这很好。然而,根据这个推理,您可以绝对在任何地方特化一个模板,因为您总是在包含所有内容的全局 namespace 中。所以我很确定 GCC 在这里的行为过于宽容,而且是一个错误。您也应该尝试使用其他编译器进行此操作,然后提交错误,或者可能是针对标准的缺陷报告。
关于c++ - 模板特化/初始化和命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21041369/