template <typename T>
void show(T&); // #1
template <typename T>
void show(T const&); // #2
int main()
{
int a = 0;
show(a); // #1 to be called
}我对这些偏序规则感到困惑。以下是一些名言:[temp.deduct.partial]/5
在完成偏序之前,对用于偏序的类型执行某些转换:
P是引用类型,则将P替换为所引用的类型。A是引用类型,则将A替换为所引用的类型。如果
P和A都是引用类型(在被替换为上面提到的类型之前),请确定这两种类型中哪种类型(如果有的话)比另一种类型更符合cv条件;否则,就偏序而言,这些类型被视为同样的cv限定类型。这一决定的结果将在下文中使用。
删除任何顶级cv-限定符:
P是cv限定类型,则P将被P的cv非限定版本所取代.A是cv限定类型,则A将被A的cv非限定版本所取代.首先,void show(T&)和void show(T const&)都可以通过传递int lvalue来调用,因此我们需要使用偏序规则来决定哪个函数更匹配。然后,根据上面的引号,我们进行了一些转换。步骤1:
T& => T #3
T const& => T const #4第2步:
T => T #5
T const => T #6#5 => #6,#6 => #5,演绎在两个方向都成功。然后,以下规则起作用:[temp.deduct.partial]/9
如果对于给定类型,扣减在两个方向上都成功(即,在上述转换之后,类型是相同的),并且
P和A都是引用类型(在被上面提到的类型替换之前):
因此,#4比#3更专业化。对于给定的值a,应该调用#2函数,但实际上调用了#1函数。为什么?我的理解有什么问题吗?
发布于 2019-12-12 10:09:28
在本例中,不使用“更专门化”规则,这是一个在排序隐式转换序列不确定函数顺序的情况下的平局规则:[over.match.best]/1。
定义ICSi(F)如下: ..。 根据这些定义,一个可行的函数F1被定义为比另一个可行函数F2更好的函数,如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,那么
在这种情况下,仅对隐式转换序列进行排序就足以确定排序,因此忽略了“或者,如果不是这样”之后的所有内容。扣减在(int&)中为#1,在(int const&)中为#2,因此在这两种情况下,引用绑定(a到int&,a到int const&)导致身份转换,而不考虑cv-资格:[over.ics.ref]/1。
当引用类型的参数直接绑定到参数表达式时,隐式转换序列是标识转换,除非参数表达式的类型是参数类型的派生类,在这种情况下,隐式转换序列是派生到基转换(over.best.ics)。..。
然而,ICS1(#1)是一个比ICS1(#2)更好的转换序列,因为[over.ics.rank]/3的存在
两个相同形式的隐式转换序列是不可区分的转换序列,除非适用下列规则之一:
- [...]
- ([3.2.6](https://timsong-cpp.github.io/cppwp/n4659/over.ics.rank#3.2.6)) S1 and S2 are reference bindings ([dcl.init.ref]), and the types to which the references refer are the same type except for top-level cv-qualifiers, **and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers**.
因此,ICS1( F1 )是一个比ICS1( F2 )更好的转换序列,因此F1优于[over.match.best]/(1.3) ([over.match.best]/(1.3))中的F2。不使用[over.match.best]/(1.7)规则。
在相反的情况下使用“更专门的”规则:
int const a = 0;
show(a); // #2 should be called for a const lvalue这一次,演绎的结果是int const&和int const&,所以[over.match.best]/(1.7)开始了。正如您所观察到的,结果是#2是一个比#1更好的函数。
(强调我的,所有引号)
https://stackoverflow.com/questions/59296834
复制相似问题