代码之家  ›  专栏  ›  技术社区  ›  Passer By

T*…上的偏序与常数T&

  •  2
  • Passer By  · 技术社区  · 6 年前

    cppreference 声明如下

    template <class ...T> int f(T*...);  // #1
    template <class T>  int f(const T&); // #2
    f((int*)0); // OK: selects #1
                // (was ambiguous before DR1395 because deduction failed in both directions)
    

    如果我们跟着 DR1395 我们看到了

    如果A是从函数参数包转换而P不是参数包,则类型推断失败。否则,使用 使用 根据17.9.2.5中所述,对产生的P型和A型进行扣减[温度类型]. 如果P是函数参数包,则将参数模板的每个剩余参数类型的类型a与函数参数包的声明器id的类型P进行比较。每次比较都会为函数参数包展开的模板参数包中的后续位置推导模板参数。 类似地,如果从函数参数包转换了,则会将其与参数模板的每个剩余参数类型进行比较。 如果对给定类型的演绎成功,则参数模板中的类型至少与参数模板中的类型一样专用。

    如果在考虑上述因素之后,函数模板F至少与函数模板G一样专用,反之亦然,并且如果G有一个尾随参数包,而F没有对应的参数,并且如果F没有尾随参数包,那么F比G更专用。

    根据我的推断,这意味着我们应该匹配从 T*... const T& 反之亦然。在这种情况下, T* 比…更专业 常量(&A); ( T U* 成功, T型* U

    然而,编译人员不同意。 Clang thinks it's ambiguous gcc thinks the second should be called ,两者都不同于cppference。

    正确的行为是什么?

    0 回复  |  直到 4 年前
        1
  •  8
  •   Barry    6 年前

    CWG 1825 ). 让我们从两个方面来进行扣除。


    template <class ...T> int f(T*...); const U& . 这失败了,无法推断 T* 常量(&A); -事实上,这是一个包在这里是无关紧要的。所以#2至少没有#1那么专业。


    推演 template <class T> int f(const T&); U*... A 从函数参数包和 P

    类似地,如果从函数参数包转换了,则会将其与参数模板的每个剩余参数类型进行比较。

    U* ,将其自身添加到剩余的每个参数类型 const T& . 这个推论是成功的。所以#1至少和#2一样专业。


    因此,现在1比2更专业。您引用的关于后续参数包的引用不适用,因为我们没有这样的情况,即每个函数模板至少与另一个函数模板一样专用。还有你引用的另一句话( [temp.deduct.type]/10 是关于推导函数类型的,所以我认为它在这里也不适用?尽管我也不确定这一节中的例子——或者这个特定规则的实际含义。