[英]template specialization/initializations and namespaces?
关于模板专业化和名称空间限定的C ++规则是什么? 我有一些代码可以归结为以下代码,这使我意识到我不了解C ++有关模板专门化初始化的规则。 首先,对我来说似乎很奇怪,甚至在h
内甚至允许g::F<>
的专业化,但是鉴于此,我不知道事情为什么如此行事。
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
,但是h
在g
内,因此专业化也在g
内,从技术上讲,这很好。 但是,通过这种推理,您可以绝对在任何地方对模板进行专业化处理,因为您始终位于全局名称空间中,该名称空间将所有内容都包含在内。 因此,我很确定GCC在这里的行为过于宽松,并且存在错误。 您也应该与其他编译器一起尝试此操作,然后提交一个错误,或者根据标准提交缺陷报告。
在:
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
这样拼写出来的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.