T*上的部分排序...和康斯特·
Partial ordering on T*... and const T&
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不是参数包,则类型扣除失败。否则,使用使用使用结果类型P和A,然后按照17.9.2.5 [temp.deduct.type]中所述进行扣除。如果p是函数参数包,则将参数模板的每个剩余参数类型的类型A与函数参数pack的声明器ID的类型P进行比较。每个比较都将模板参数推论,以通过功能参数包扩展的模板参数包中的后续位置。类似地,如果A从函数参数包进行转换,则将其与参数模板的每个剩余参数类型进行比较。如果给定类型的扣除成功,则认为参数模板的类型被认为是至少与参数模板的类型一样专业。[...]
如果在考虑上述函数模板F之后,函数模板F至少与函数模板g和vice-vice-a一样专业,并且如果g具有thailter param pack,则f f f function f具有相应的参数,以及如果f没有尾随的参数包,那么f比g。
更专业
根据我可以推断的内容,这意味着我们应该匹配从T*...
扩展到const T&
的每个单独类型,反之亦然。在这种情况下,T*
比const T&
更专业(U*
的T
成功,T*
来自U
失败)。
但是,编译器不同意。Clang认为这是模棱两可的,海湾合作委员会认为应该称呼第二个,这两种都与CPPReference不同。
正确的行为是什么?
cppReference对于此示例是正确的(这正是CWG问题的示例,以及CWG 1825)。让我们通过两种方式进行推论。
从const U&
推导template <class ...T> int f(T*...);
。这是失败的,无法从const U&
推导T*
-这是这里的包装并不重要的事实。因此,#2至少不如#1。
从U*...
推导template <class T> int f(const T&);
,我们曾经具有"如果A
是从函数参数pack转换的,而P
不是参数包,则类型扣除失败。" - 这意味着我们甚至在尝试做其他任何事情之前就失败了。但是CWG 1395删除了该句子,所以我们继续前进,我们有新句子:
同样,如果A从函数参数包转换,则将其与参数模板的每个剩余参数类型进行比较。
我们本身将U*
与剩余的参数类型(即const T&
)进行比较。这种推论成功了。因此,#1至少与#2一样专业。
结果,现在#1比#2更专业。您引用的关于落后参数包的报价不适用,因为我们没有每个功能模板至少与另一个功能一样专业的情况。另外,您引用的其他报价([temp.deduct.type]/10是关于推论功能类型,所以我认为它也不适用吗?尽管我也不确定该部分中的示例 - 或什么特定规则实际上是指。
- 康斯特指针C++斯特劳斯特鲁普
- Static_cast 对于康斯特来说,会抛弃预选赛
- 东康斯泰克普/康斯蒂尼特/康斯特瓦尔在C++20 中允许吗?
- 康斯特正确性建议
- 从字符到康斯特* 字符的转换无效,代码有什么问题?
- T*上的部分排序...和康斯特·
- 调用"树:<int>:运算符==(树*&<int><int>,树*&)康斯特"没有匹配函数
- 抛弃康斯特,就是这种定义明确的行为
- 错误:类型为 '.&' 来自类型的临时 '..*康斯特'
- 无法push_back移动(不可复制与康斯特字段)到矢量
- 传递康斯特字符*的值
- mpg123_open()和康斯特
- 康斯特指针浅拷贝
- C++ wifstream:不兼容的字符常量*,wchar_t康斯特*类型
- 康斯特是谎言吗?(因为康斯特可以被抛弃)
- 康斯特·查尔 * 变得腐败
- 康斯特查尔..改变
- 康斯特与 #define(奇怪的行为)
- 这是抛弃康斯特吗?
- 第二个康斯特在"const int const &someval"做什么?