多个运算符匹配这些操作数

时间:2011-08-24 22:04:39

标签: c++

假设我们有下一个代码:

struct int64
{
    long long value;

    int64() : value(0) {}
    int64(signed char i8) : value(i8) {}
    int64(unsigned char u8) : value(u8) {}
    int64(short i16) : value(i16) {}
    int64(unsigned short u16) : value(u16) {}
    int64(int i32) : value(i32) {}
    int64(unsigned u32) : value(u32) {}
    int64(long long i64) : value(i64) {}
    int64(unsigned long long u64) : value(u64) {}
    int64(const int64& i64) : value(i64.value) {}

    int64& operator+=(const int64& rhs) { return value += rhs.value, *this; }
    int64& operator-=(const int64& rhs) { return value -= rhs.value, *this; }

    friend int64 operator+(const int64& lhs, const int64& rhs) { return int64(lhs) += rhs; }
    friend int64 operator-(const int64& lhs, const int64& rhs) { return int64(lhs) -= rhs; }

    operator  char() const { return (char)value;  }
    operator short() const { return (short)value; }
    operator int() const { return (int)value; }
    operator long long() const { return value; }
};

编译此代码时:

int64 q = 500;
int64 m = q + 1024;

发生错误,因为1024有4个类似的转换,q有一个转换为整数类型,为了解决这个问题,我从operator XX删除了int64并添加了以下代码:

template <typename n>
operator n() const { return (n)value; }

现在我可以执行以下代码:

int64 q = 500;
int64 m = q + 1024;
short r = q;

模板定义适用于Visual C++GCC编译器,但Intel C++编译器。

如何编写适用于这些编译器的转换运算符?

3 个答案:

答案 0 :(得分:1)

您应该为您支持的所有类型编写operator+个定义:

int64 operator+(int num) {
    return int64(value + num);
}

int64 operator+(short num) {
    ...
}

...

您正在向int添加int64并将结果分配给int64,但它没有复制构造函数,因此它将其转换为某种整数类型并尝试与所有转换运算符和构造函数做一些奇怪的事情。

答案 1 :(得分:0)

这里的问题是,如果同时提供内置类型的构造函数和相同类型的转换运算符TO,然后使用两种类型的表达式,C ++无法确定它应该采用哪种方式的优先级走。因此,“myInt64Variable + 1024”可以通过转换为int运算符表示“(int)myInt64Variable + 1024)”,或者通过构造函数表示“myInt64Variable +(int64)1024”。

根据我的经验,处理此问题的最佳方法是不提供转换运算符,或者如果必须使用转换运算符,则可以创建toInt()函数或类似函数。从您的自定义类型到内置类型的任何转换都将是有损的,或者为什么要使用自定义类型?并且让人们注意到他们执行有损转换是一件好事。

答案 2 :(得分:0)

从C ++ 11开始(在询问此问题时刚刚批准),您可以标记转换explicit

struct int64
{
    // ...

    explicit operator  char() const { return (char)value;  }
    explicit operator short() const { return (short)value; }
    explicit operator int() const { return (int)value; }
    explicit operator long long() const { return value; }
};

这应该适用于所有主要编译器的最新版本(我测试过的所有编译器都有足够的C ++ 11支持)。如果你愿意,你也可以将它应用于你的模板化转换运算符,虽然我更喜欢四个非模板化的转换(加上,这使我试过的ICC版本崩溃了!):

struct int64
{
    // ...

    template <typename n>
    explicit operator n() const { return static_cast<n>(value); }
};

但是,这意味着您无法执行short r = q;。对我来说,这是一件好事,因为缩小转换真的应该是

short r = static_cast<short>(q);