首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何理解T&和T&的偏序规则

如何理解T&和T&的偏序规则
EN

Stack Overflow用户
提问于 2019-12-12 02:26:17
回答 1查看 153关注 0票数 5
代码语言:javascript
复制
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替换为所引用的类型。

[temp.deduct.partial]/6

如果PA都是引用类型(在被替换为上面提到的类型之前),请确定这两种类型中哪种类型(如果有的话)比另一种类型更符合cv条件;否则,就偏序而言,这些类型被视为同样的cv限定类型。这一决定的结果将在下文中使用。

[temp.deduct.partial]/7

删除任何顶级cv-限定符:

  • 如果P是cv限定类型,则P将被P的cv非限定版本所取代.
  • 如果A是cv限定类型,则A将被A的cv非限定版本所取代.

首先,void show(T&)void show(T const&)都可以通过传递int lvalue来调用,因此我们需要使用偏序规则来决定哪个函数更匹配。然后,根据上面的引号,我们进行了一些转换。步骤1:

代码语言:javascript
复制
T&       => T          #3
T const& => T const    #4

第2步:

代码语言:javascript
复制
T       => T    #5
T const => T    #6

#5 => #6#6 => #5,演绎在两个方向都成功。然后,以下规则起作用:[temp.deduct.partial]/9

如果对于给定类型,扣减在两个方向上都成功(即,在上述转换之后,类型是相同的),并且PA都是引用类型(在被上面提到的类型替换之前):

  • 如果来自参数模板的类型是lvalue引用,而来自参数模板的类型不是,则参数类型不被认为至少与参数类型一样专业化;
  • 否则,如果参数模板中的类型比参数模板中的类型更符合cv条件(如前所述),则参数类型不被认为至少与参数类型一样专门化。

因此,#4#3更专业化。对于给定的值a,应该调用#2函数,但实际上调用了#1函数。为什么?我的理解有什么问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-12 10:09:28

在本例中,不使用“更专门化”规则,这是一个在排序隐式转换序列不确定函数顺序的情况下的平局规则:[over.match.best]/1

定义ICSi(F)如下: ..。 根据这些定义,一个可行的函数F1被定义为比另一个可行函数F2更好的函数,如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,那么

  • (1.3)对于某些参数j,ICSj(F1)是一个比ICSj(F2)、或(如果不是那样的话) 更好的转换序列。
  • ..。
  • (1.7) F1和F2是函数模板的专门化,根据temp.func.order、描述的偏序规则,F1的函数模板比F2的函数模板更专业化,如果不是这样的话,
  • ..。

在这种情况下,仅对隐式转换序列进行排序就足以确定排序,因此忽略了“或者,如果不是这样”之后的所有内容。扣减在(int&)中为#1,在(int const&)中为#2,因此在这两种情况下,引用绑定(aint&aint const&)导致身份转换,而不考虑cv-资格:[over.ics.ref]/1

当引用类型的参数直接绑定到参数表达式时,隐式转换序列是标识转换,除非参数表达式的类型是参数类型的派生类,在这种情况下,隐式转换序列是派生到基转换(over.best.ics)。..。

然而,ICS1(#1)是一个比ICS1(#2)更好的转换序列,因为[over.ics.rank]/3的存在

两个相同形式的隐式转换序列是不可区分的转换序列,除非适用下列规则之一:

  • ..。
  • (3.2)标准转换序列S1比标准转换序列S2更好
代码语言:javascript
复制
- [...]
- ([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)规则。

在相反的情况下使用“更专门的”规则:

代码语言:javascript
复制
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更好的函数。

(强调我的,所有引号)

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59296834

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档