Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 铸造操作员总是模棱两可_C++_Casting - Fatal编程技术网

C++ 铸造操作员总是模棱两可

C++ 铸造操作员总是模棱两可,c++,casting,C++,Casting,考虑以下示例: 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() {

考虑以下示例:

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
}

当我调用casting时失败:从
q
m
的模糊转换。为什么会这样?我真的不明白。我明确地为
m
添加了一个强制转换操作符!为什么这应该是模棱两可的?但是,如果我将强制转换删除为
double
,这会起作用。这有什么关系?如何做我想做的事情?

考虑编译器在执行以下操作时可能采用的路径:

m temp__(x);
有三个相关的施工人员:

m(int );      // (A)
m(const m& ); // (B)
m(m&& );      // (C)
我们可以通过
x-->double-->int
调用
(A)
,这是一个用户定义的转换序列

我们可以通过
x-->m
调用
(B)
(C)
,这也是一个用户定义的转换序列

用户定义的转换序列只有在调用同一个构造函数时才能成为另一个的首选项。但是在本例中,它们没有-因此编译器无法选择其中一个。因此,这是不明确的

你的选择是

  • 直接调用您的操作员(或使其成为具有某个名称的函数);或
  • 使
    q
    m
    继承-与用户定义的转换序列相比,更倾向于派生到基的转换;或
  • 使两个转换运算符都显式——在这种情况下,一开始只有一个可行的候选者,因此不会有歧义

当我用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\u类(q const&)
  • 因此,如果存在,则需要从
    q
    转换为其他11种类型之一, 在诊断中枚举,从中可以构造一个
    mpf\U类
  • 但是有两个这样的转换,每一个都和另一个一样好,多亏了 您提供的两个强制转换运算符
    q
转换
运算符double()
可以满足11个构造函数中的第一个 而
操作符mpf\u class()
可以满足最后的要求。编译器没有依据 用于首选这些构造函数中的任何一个

如果你牺牲一个或另一个施法者,问题就会消失。 如果你必须同时拥有它们,那么你也可以通过同时拥有它们来解决问题 <代码>显式< /代码>,这样编译器将不会考虑调用转换,除非调用显式性:

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;
}

如果我将强制转换移除为double,它也会起作用,但如果我只想强制转换为double,那么这反过来意味着性能会下降。如果定义了
mpf_类
?它是什么?mpf_类是GMP(Gnu多精度)库中的主要类之一。您是否尝试过在
操作符之前使用
显式
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;
}
explicit operator double() const
{
    return i;
}
explicit operator mpf_class() const
{
    return i;
}