为什么将“&&true”添加到约束会使函数模板成为更好的重载?
考虑函数模板的以下两个重载foo:
template <typename T>
void foo(T) requires std::integral<T> {
std::cout << "foo requires integraln";
}
template <typename T>
int foo(T) requires std::integral<T> && true {
std::cout << "foo requires integral and truen";
return 0;
}
请注意两个约束之间的区别:第二个约束有一个额外的&& true.
直观地说,true在连词中是多余的(因为X && trueis just X)。然而,它看起来像这使得语义差别,如foo(42)将调用第二个过载。
为什么会这样?具体来说,为什么第二个函数模板是更好的重载?
回答
根据[temp.constr.order],特别是[temp.constr.order]/1和[temp.constr.order]/3
/1 约束
P包含约束Q当且仅当,[...] [ 示例:让 A 和 B 成为原子约束。约束A ? B包含A但A不包含A ? B。约束A包含A ? B但A ? B不包含A。另请注意,每个约束都包含自身。— 结束示例 ]/3 声明
D1至少与声明一样受到约束,D2如果
- (3.1)
D1和D2均为约束的声明和D1的相关联的约束归入那些D2; 或者- (3.2) D2 没有相关的约束。
如果我们考虑Aasstd::integral<T>和Bas true; 然后:
A ? B这是std::integral<T> && truesubsumesA,这是std::integral<T>,
这意味着对于以下声明:
// Denote D1
template <typename T>
void foo(T) requires std::integral<T> && true;
// Denote D2
template <typename T>
void foo(T) requires std::integral<T>;
的相关联的约束D1归入那些的D2,因此D1 至少与约束为D2。同时,反向不成立,而D2 不是至少为约束的D1。这意味着,根据[temp.constr.order]/4
的声明
D1比另一声明更多的限制D2时D1至少与作为约束D2,而D2不是至少为限制,因为D1。
声明比声明D1 更受约束D2,D1随后根据[temp.func.order]/2被重载决议选择为最佳匹配:
部分排序通过依次转换每个模板(见下一段)并使用函数类型执行模板参数推导来选择两个函数模板中的哪一个比另一个更专业。推导过程确定模板中的一个是否比另一个更专业。如果是这样,则更专业的模板是偏序过程选择的模板。如果两个推导都成功,则偏序选择更受约束的模板(如果存在),如下所示。
THE END
二维码