使用显式用户定义的强制转换运算符调用函数是不明确的
Calling function with explicit user defined cast operator is ambigous
我遇到了一个问题,这对我来说很难解释。以下是最小的、可重现的代码,在 GCC 6.2 和 Clang 3.9 上都失败了:
class T2;
class T1
{
int field1;
public:
T1(int pf) : field1(pf) {}
operator int() { return field1; }
operator T2();
};
class T2
{
int field2;
public:
T2(int pf) : field2(pf) {}
};
T1::operator T2() { return T2(field1); }
void foo(T2 pt) {}
int main()
{
T1 obj1(1);
T2 obj2(2);
foo((T2) obj1); // ambiguous conversion for C-style cast from 'T1' to 'T2'
foo(T2(obj1)); // ambiguous conversion for functional-style cast from 'T1' to 'T2'
foo(static_cast<T2>(obj1)); // ambiguous conversion for static_cast from 'T1' to 'T2'
}
请注意,我没有编写特定的构造函数来从 T1 转换为 T2,所以我想编译器应该很清楚,唯一的方法是使用用户定义的强制转换运算符。
奇怪的事实是,当我注释掉一个看似无关的演员时:
// operator int() { return field1; }
然后代码编译起来很麻烦。这是什么原因呢?
(T2) obj1
的意思与T2(obj1)
完全相同(在这种情况下为static_cast<T2>(obj1)
(,但也许更容易推理这种类似构造函数的语法。
按原样使用代码时,有两个选项:
- 用
int
构造T2
,由用户定义的转换算子得到int
- 根据用户定义的转换运算符获得的
T2
构造T2
T2
根据 N4140:
如果只有一个可行的函数比 所有其他可行的函数,那么它是重载选择的函数 分辨率;否则调用格式不正确
相同形式的两个隐式转换序列是 无法区分的转换序列,除非符合以下条件之一 规则适用:
- 用户自定义的转化序列
U1
是比另一个用户定义的转化序列更好的转化序列U2
如果他们 包含相同的用户定义的转换函数或构造函数,或 它们在聚合初始化和 无论哪种情况,U1
的第二个标准转换序列都更好 比第二标准转换序列U2
。
由于这不适用,因此两种转换都不比另一种更好。
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 构造函数和转换运算符之间的重载解析
- 分配给转换运算符失败-C++
- 转换运算符不适用于sleep_until
- 尝试使用算术运算符阻止隐式转换
- 错误 C2679:二进制"<<":未找到采用类型 'std::string_view' 的右侧操作数的运算符(或者没有可接受的转换)
- 是否可以将带有字符串化运算符的宏转换为 constexpr?
- C2678 二进制 '==':未找到采用 'Card' 类型左操作数的运算符(或者没有可接受的转换)
- 继承模板化转换运算符
- 将 OR 逻辑运算符从 C++ 转换为 Fortran
- 模板转换运算符在 clang 6 和 clang 7 之间的区别
- 如何在C++中正确重载运算符转换字符*?
- 将私有结构哈希器运算符转换为静态
- 混合类型的Boost运算符-转换和私有成员
- 如何将 c++ 运算符转换为 Java
- 运算符转换,GCC 和 clang:哪个编译器是正确的
- 将 istream 运算符>>转换为 istream getline
- 在C++中,将任意在位运算符转换为一元运算符
- 将运算符转换为 std::复杂<double>
- 为什么按位否定运算符"~"转换为 int?(从"int"转换为"无符号字符"可能会改变其值)