模板专用化/初始化和命名空间



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上测试的,到目前为止看起来有点像一个bug…)

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

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

当这一行开始时,您处于全局名称空间中。因此,g::N必然是合格的,g::F<float>也是合格的。

然而,当你通过了你所专门化的东西(即在n_s之后),你现在就在你所专业化的东西的范围内,即g::F内部。所有进一步的查找都是在此范围内完成的,因此x必须限定为h::X

也就是说,虽然允许在包含原始名称空间的名称空间中进行专门化,但在嵌套名称空间(在您的情况下为h)内进行专门化在我看来很奇怪,但这里的标准有点模糊,正如14.7.3/2中所说:"应在包含专门化模板的名称空间内声明显式专门化。">

全局名称空间包含F,所以这很好,g也是如此。h不包含F,但hg内,因此专业化也在g内,这在技术上使得这很好。然而,通过这种推理,你可以在任何地方专门化一个模板,因为你总是在全局命名空间中,它包含了所有内容。所以我非常确信GCC在这里的行为过于宽容,而且是一个错误。您也应该在其他编译器中尝试一下,然后根据标准提交一个bug,或者可能是一个缺陷报告。

In:

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

它失败是因为与F<int>::n_s关联的命名空间是g,而X是在g::h中声明的。这就是为什么你需要把它拼写成h::F<int>::n_s

相关内容

  • 没有找到相关文章

最新更新