考虑以下示例:
struct m
{
m(int ) { }
};
class q
{
public:
int i;
q(int i)
{
this->i = i;
}
operator double()
{
return (double) i;
}
operator m()
{
return (m)i;
}
};
int main()
{
q x(1);
(m)x; // error: ambiguous
}
当我调用强制转换时失败:从q
到m
的模糊转换。为什么这样?我真的不明白。我明确地为m
添加了一个强制转换运算符!为什么这应该是模棱两可的?但是,如果我将演员表移至double
,则可行。为什么这么重要?我怎么能做我想做的事?
答案 0 :(得分:2)
考虑编译器执行的可能路径:
m temp__(x);
有三个相关的构造函数:
m(int ); // (A)
m(const m& ); // (B)
m(m&& ); // (C)
我们可以通过(A)
拨打x --> double --> int
,这是用户定义的转化顺序。
我们可以通过(B)
拨打(C)
或x --> m
,这也是用户定义的转化顺序。
如果用户定义的转换序列最终调用相同的构造函数,则它们只能是对另一个的首选项。但在这种情况下,他们没有 - 因此编译器无法选择其中一个。因此,含糊不清。
您的替代方案是
q
继承自m
- 派生到基础的转换将优先于用户定义的转换序列;或explicit
- 在这种情况下,只有一个可行的候选者开始,所以不会有歧义。答案 1 :(得分:0)
当我使用g ++ 5.1编译你的程序时,我得到:
/home/imk/develop/so/mpf_cast/main.cpp:35:25: error: call of overloaded ‘__gmp_expr(q&)’ is ambiguous
cout << (mpf_class) x << endl;
^
/home/imk/develop/so/mpf_cast/main.cpp:35:25: note: candidates are:
In file included from /home/imk/develop/so/mpf_cast/main.cpp:2:0:
/usr/include/gmpxx.h:1883:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(double)
__gmp_expr(double d) { mpf_init_set_d(mp, d); }
^
/usr/include/gmpxx.h:1880:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(float)
__gmp_expr(float f) { mpf_init_set_d(mp, f); }
^
/usr/include/gmpxx.h:1876:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(long unsigned int)
__gmp_expr(unsigned long int l) { mpf_init_set_ui(mp, l); }
^
/usr/include/gmpxx.h:1873:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(long int)
__gmp_expr(signed long int l) { mpf_init_set_si(mp, l); }
^
/usr/include/gmpxx.h:1869:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(short unsigned int)
__gmp_expr(unsigned short int s) { mpf_init_set_ui(mp, s); }
^
/usr/include/gmpxx.h:1866:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(short int)
__gmp_expr(signed short int s) { mpf_init_set_si(mp, s); }
^
/usr/include/gmpxx.h:1862:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(unsigned int)
__gmp_expr(unsigned int i) { mpf_init_set_ui(mp, i); }
^
/usr/include/gmpxx.h:1859:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(int)
__gmp_expr(signed int i) { mpf_init_set_si(mp, i); }
^
/usr/include/gmpxx.h:1855:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(unsigned char)
__gmp_expr(unsigned char c) { mpf_init_set_ui(mp, c); }
^
/usr/include/gmpxx.h:1852:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(signed char)
__gmp_expr(signed char c) { mpf_init_set_si(mp, c); }
^
/usr/include/gmpxx.h:1837:3: note: __gmp_expr<__mpf_struct [1], __mpf_struct [1]>::__gmp_expr(const __gmp_expr<__mpf_struct [1], __mpf_struct [1]>&)
__gmp_expr(const __gmp_expr &f)
^
问题演员表达(mpf_class) x
需要mpf_class
(typedef __gmp_expr<mpf_t, mpf_t> mpf_class
)
从q
构建。所以你也可以考虑
q x(1);
mpf_class m(x);
引起相同的诊断。
为什么建筑模糊不清?因为: -
mpf_class(q const &)
q
转换为其他11种类型之一,
在诊断中列举,可以构建mpf_class
q
的两个演员操作员。转换operator double()
可以满足11个构造函数中的第一个
并且operator mpf_class()
可以满足最后一个。编译器没有基础
更喜欢这些构造函数。
如果牺牲一个或另一个施法操作员,问题就会消失。
如果你必须同时拥有它们,那么你也可以通过制作它们来解决它
explicit
,以便编译器不会考虑调用转换,除非它被明确调用:
explicit operator double()
{
return (double)i;
}
explicit operator mpf_class()
{
return (mpf_class)i;
}
然后你会发现,例如:
int main()
{
q x(1);
mpf_class mpf(x); // via `explicit operator mpf_class()`
double d(x); // via `explicit operator double()`
// d = q(2); <- does not compile
d = static_cast<double>(q(2));
// mpf = q(2); <- does not compile
mpf = static_cast<mpf_class>(q(2));
return 0;
}
顺便提及:
const
因此:
explicit operator double() const
{
return i;
}
explicit operator mpf_class() const
{
return i;
}