【发布时间】:2020-02-27 18:45:20
【问题描述】:
我在转换运算符匹配时遇到了 GCC 和 clang 之间的差异(在 godbolt 测试的大范围版本 - 都具有相同的差异)。现在使用 Barry 的更短的复制代码 - 也可在 godbolt 获得。
struct X {
template <typename T>
operator T const&() const;
};
int i = X();
在转换为int 时应该operator T const&() const 匹配(clang 说是/GCC 需要operator T() const 来避免:
<source>:6:9: error: cannot convert 'X' to 'int' in initialization
6 | int i = X();
| ^~~
C++17 标准的相关部分是15.3 Conversions [class.conv]。其中,15.3.5 说...
函数重载决议 (16.3.3) 选择最佳转换函数来执行转换。
...这几乎是最重要的。 16.3.3 是 最佳可行函数 [over.match.best] 部分,但通常与 16.3.2 可行函数 [over.match.viable] 组合使用。该标准似乎没有明确说明 16.3.2 是否适用于此,但假设适用,我们在 16.3.2.1 中有:
从为给定上下文 (16.3.1) 构建的候选函数集合中,选择一组可行函数
这引发了 GCC 是否认为 operator const T&() const 是不可行的候选人,甚至不是候选人的问题。候选有效的要求非常简单:正确数量的参数,并且 “每个参数都应该存在一个隐式转换序列(16.3.3.1),将该参数转换为相应的参数...... ",这里显然是正确的,所以我认为 GCC 一定不能将 operator const T&() const 视为候选者,这将我们带到 16.3.1 候选函数和参数列表 [over.match.funcs],特别是 16.3.1/7:
在候选函数模板的每种情况下,候选函数模板特化是 使用模板参数推导(17.8.3、17.8.2)生成。然后将这些候选人处理为 以通常的方式候选函数。
假设 template <typename T> void f(const T&); 可以使用 int 参数类型调用,我认为 GCC 应该将转换运算符视为有效候选者,就像 clang 一样。
我会很感激确认/想法。如果大家都同意,我会针对 GCC 提出错误报告。
【问题讨论】:
-
您的问题的复制时间要短得多:godbolt.org/z/giDKSP
-
不管怎样,MSVC 也可以编译。
-
这里的规则非常模糊,我不确定我们甚至不知道我们想要他们说什么。
-
@Barry:在 Godbolt Demo with one operator Demo with both operators 中有一个“新的”一致性视图。
标签: c++ gcc c++17 language-lawyer conversion-operator