提问者:小点点

为什么在约束中添加“&&true”使函数模板成为一个更好的重载?


考虑函数模板foo的以下两个重载:

template <typename T>
void foo(T) requires std::integral<T> {
    std::cout << "foo requires integral\n";
}

template <typename T>
int foo(T) requires std::integral<T> && true {
    std::cout << "foo requires integral and true\n";
    return 0;
}

注意这两个约束之间的区别:第二个约束有一个额外的&true

直观地说,true在连词中是多余的(因为x&&true只是x)。但是,看起来这会产生语义上的差异,因为foo(42)会调用第二个重载。

为什么会这样呢?具体来说,为什么第二个函数模板是一个更好的重载?


共1个答案

匿名用户

根据[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)D1D2都是约束声明,D1的关联约束包含了D2的约束;或
  • (3.2)D2没有关联的约束。

如果我们认为Astd::integralBtrue;然后:

  • a√b,即std::integral&true包含a,即std::integral

意味着下列声明:

// 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一样受到约束;根据[temp.func.order]/2,重载结果选择约束更多的声明d1作为最佳匹配:

偏序选择两个函数模板中哪一个比另一个更专门化,方法是依次转换每个模板(请参阅下一段),并使用函数类型执行模板参数推导。扣减过程确定其中一个模板是否比另一个模板更专门化。如果是,则偏序过程选择的模板是更专门的模板。如果两个推导都成功,则偏序选择约束较多的模板(如果存在),如下所确定的。