22
|
Johannes Schaub - litb · 技术社区 · 15 年前 |
1
6
这是我的任务。我同意
Charles Bailey
错误的步骤是从
我们要采取的步骤是: 145.5.2/2
145.5.2/3-B1
在我看来,这些类型的合成如下:
我看不出任何措辞要求
因此,现在我们执行扣除步骤: Q2到T1 我们尝试推导T1的模板参数,因此我们得出:
即使参数2是非推导上下文,推导仍然成功,因为我们有一个T的值。 Q1到T2 推导出t2的模板参数,我们有:
imho,这是标准让我们失望的地方。参数不依赖,所以不清楚应该发生什么,但是,我的经验(基于14.8.2.1/3的斜视读数)是,即使参数类型P不依赖,参数类型A也应该匹配它。 T1的合成参数可以用来专门化T2,但不能反过来。因此,t2比t1更专业,因此是最佳功能。 更新1:
只是为了掩盖
在上面,
更新2
当
我不知道部分排序算法如何正确地实例化
|
2
2
编辑:学习后
Clang's
(由Doug Gregor)实现了他们的部分排序算法,我同意海报的其余部分,即最初的示例不是“有意的”模棱两可的——尽管标准并没有像它那样清楚地说明在这种情况下应该发生什么。我已经编辑了这篇文章,以表明我的修改想法(为了我自己的利益和参考)。尤其是Clang的算法阐明了
最初我想知道为什么以下内容被认为是模棱两可的:
但以下内容不会模棱两可:
(如果发生以下情况,人们可能会认为这是不明确的原因:
在研究了Clang的部分排序算法之后,很明显他们将上面的“3”视为:
因此,对“typename x::type”进行某些唯一“u”的推导将成功-
所以“2”显然比“3”更专业。 |
3
1
我想知道这是否是一个正确的简化。当你合成类型
这意味着
|
4
1
编辑:请忽略这篇文章-在研究了道格·格雷戈(Doug Gregor)实现的部分排序的clangs算法之后(尽管它在本文中只部分实现了一部分-似乎与OP问题相关的逻辑已经充分实现了)-它似乎将未减少的上下文视为另一个TE。MPlate参数。这表明显式void*参数的重载应该是更专门化的版本,不应该有歧义。像往常一样,科莫是正确的。 至于标准中明确定义这种行为的措辞,那是另一回事…… 因为这篇文章也是在comp.lang.c++上发表的,而且似乎也引起了一些混乱——我想我也会把我的答案贴在这里——因为讨论显然与这里提出的问题有关。
我认为这是错误的。当检查哪个功能更强大时
专门化(在部分排序期间),编译器转换
参数列表到
关于你关于部分专业化的观点-当检查 哪个模板比另一个模板更专业化,这是唯一可以使用的类型 是唯一生成的类型-如果此时有其他专门化 声明的实例化(当正在完成重载解析时) 他们将被考虑。如果您以后添加它们,它们应该被选中 您将违反ODR(根据14.7.4.1) 在 候选集的形成-但这次使用的是实际参数的类型 到函数。如果(x的)最佳匹配部分专门化导致 对于某些函数类型具有更好的隐式转换序列 参数,那么我们永远不会到达部分排序阶段,并且 “Better”(更好)功能将被选中(在将其设置为部分之前 订购阶段) 下面是一个示例,其中包含有关在各个步骤中应执行的操作的注释:
值得一提的是,如果主模板没有定义,那么sfinae在部分排序阶段运行, 两者都不能从另一个推论出来,因此会产生歧义。 另外,如果您添加另一个模板,如果这些函数的实例化点移动到翻译单元中的其他位置,则会导致另一个匹配,那么您将明显违反ODR。
这里没有争论。 但是根据目前的规则,OP的例子必须是 模棱两可的。 最后,下面是对LITB提出的两个具体问题的明确、明确的答案:
1)现在是否将使用第一个参数推导出的t值?
2)现在,为什么实现会说第二个更专业化?
我希望这能解决这个问题-如果还有什么不清楚的地方请告诉我:)
编辑:
Litb在他的评论中提出了一个很好的观点——也许他说主要模板总是
用于唯一生成类型的实例化的语句太强。
这里必须使用斯芬纳规则——怎么可能不使用呢? 我觉得这是充分的暗示-我不会否认它可能更清楚,虽然我鼓励委员会澄清 这-我认为不需要澄清来充分解释您的示例。 让我提供一种连接它们的方法。 (14.2): “指定显式模板参数列表时,模板参数必须与 模板参数列表,并且必须生成有效的函数类型,如下所述;否则,类型推断 失败” 自(14.5.5.2/3) “使用的转换是: _ 函数参数列表中的参数,或返回类型中的模板转换函数的参数。“ 在我看来,上面的引用意味着一旦为每个模板参数“创建”了唯一的生成类型,函数声明就必须 关联性由实例化 明确地 将唯一类型作为模板参数提供给我们的函数模板。如果这导致无效 函数类型,那么不仅是转换,更重要的是后续的模板参数推导需要 部分排序功能失败。 自(14.5.5.2/4) “使用转换后的函数参数列表,对其他函数模板进行参数推导。转换后的模板 至少和其他人一样专业 如果且仅当 ,演绎成功,演绎参数类型 是完全匹配的(因此推导不依赖于隐式转换)。” 如果转换后的函数参数列表导致替换失败,那么我们就知道演绎是不可能成功的。 既然演绎没有成功,它就没有另一个那么专业了——这就是我们继续下去所需要知道的一切。 在部分排序的两个。
好吧-我想我看到了我们不同的看法。如果我正确理解你,你就是在说 当这些函数模板被声明时,编译器会跟踪它们之间的部分排序, 无论过载分辨率如何,都会被触发在它们之间进行选择。 如果这就是你解释它的方式,那么我可以理解为什么你会期望你描述的上述行为。 但我认为该标准从来没有要求或要求这样做。 现在,标准已经明确了部分排序对于调用函数的类型是不可知的(我相信 当您将其描述为静态属性并且与上下文无关时,这就是您所指的内容)。 该标准还清楚地表明,它只关心函数模板之间的部分排序(调用部分排序)。 在过载分辨率(13.3.3/1)过程中,如果且仅当它不能根据IC或 如果一个是模板,另一个不是。[类模板的部分排序部分专用化是一个单独的问题 在我看来,使用相关的上下文(其他模板定义),它需要实例化该特定类。] 因此,在我看来,因为函数模板的部分排序机制是在重载时调用的 执行解析时,必须使用上下文的相关部分(模板定义和专门化)。 在完成过载分辨率时。 基于我的兴趣,根据上面使用“template struct a”的示例,代码是有效的。 部分排序不是在定义上下文中完成的。但如果/当您碰巧调用重载解决方案时 通过写入对f((int*)0,0)的调用,在两个函数之间,当编译器 尝试组装候选声明或对其部分排序(如果到达部分排序步骤) 如果一个无效的表达式或类型作为函数类型的一部分产生,sfinae将帮助我们解决问题并告诉我们 我们认为模板推导失败(就部分排序而言,这意味着 如果我们甚至不能转换模板,就不能比另一个更专门化)。 现在关于poi——如果你像我一样确信转换函数类型应该 使用显式提供的模板参数列表(使用唯一生成的类型)表示隐式实例化 那么以下标准报价是相关的: 14.6.4.1/1对于函数模板专业化、成员函数模板专业化或 类模板的成员函数或静态数据成员(如果专门化是隐式实例化的) 因为它是从另一个模板专门化和引用它的上下文中引用的 取决于模板参数,专用化的实例化点是实例化点 封闭的专业化。 我的解释是,转换函数类型和原始函数类型的POI是 与实际函数调用创建的那些函数的POI相同。
啊-现在你提出了一个可能的解决方案,它解决了歧义,有利于我们 所有这些都是直觉上的期望——这是一个单独的问题,虽然我喜欢你前进的方向, 像你一样,在宣布它的可操作性之前,我也必须先考虑一下。 感谢您继续讨论。我希望这样做不只是限制你发表评论。 既然你可以编辑我的帖子,如果方便的话,请随时在帖子内回复。 |
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
rainer · 后台插入程序的初始化 1 年前 |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |