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

Posted

技术标签:

【中文标题】多个运算符匹配这些操作数【英文标题】:more than one operator matches these operands 【发布时间】:2011-08-24 22:04:39 【问题描述】:

假设我们有下一个代码:

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;

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

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

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


int64 operator+(short num) 
    ...


...

您将 int 添加到 int64 并将结果分配给 int64 但它没有复制构造函数,因此它将其转换为某种整数类型并尝试对所有内容进行一些奇怪的处理那些转换运算符和构造函数。

【讨论】:

@Ben 你不是通过定义一个来放弃编译器生成的(至少是复制 ctor)吗? 如果您定义任何其他构造函数,而不是复制 ctor 或赋值运算符,您将失去编译器生成的默认构造函数。 有一个复制构造函数,编译器生成的赋值运算符就可以了,这不是问题。对象 q 可以转换为整数类型,数字 1024 也可以转换为 int64 类型,这是造成歧义的原因。 @Ben 啊,我当时印象错了。 @Muhammad 也许你认为你“不应该”,但你有没有试过看看它是否能解决你的错误?【参考方案2】:

这里的问题是,如果你同时提供一个内置类型的构造函数和一个转换运算符到同一类型,然后有一个包含这两种类型的表达式,C++ 就不能真正优先考虑它应该采用的方式去。因此,“myInt64Variable + 1024”可以通过转换为 int 运算符表示“(int)myInt64Variable + 1024)”,或者通过构造函数表示“myInt64Variable + (int64)1024”。

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

【讨论】:

【参考方案3】:

从 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);

【讨论】:

以上是关于多个运算符匹配这些操作数的主要内容,如果未能解决你的问题,请参考以下文章

没有运算符匹配这些操作数

没有运算符“=”匹配这些操作数错误

错误:没有运算符“<<”与这些操作数匹配

没有运算符 << 匹配这些操作数

错误:没有运算符“<<”与这些操作数匹配

Visual Studio 手表中的向量“无运算符“[]”与这些操作数匹配错误