使用强制转换运算符和单参数构造函数的类重载运算符

Overloading operators for class with cast operator and single-argument constructor

提问人:Pavel Dubsky 提问时间:1/18/2013 最后编辑:Pavel Dubsky 更新时间:5/15/2014 访问量:457

问:

我有这样的代码

class Number
{
    int m_value;

public :
    Number(const int value) : 
        m_value(value)
    {
    }

    operator const int() const
    {
        return m_value;
    }

    int GetValue() const
    {
        return m_value;
    }
};

bool operator==(const Number& left, const Number& right)
{
    return left.GetValue() == right.GetValue();
}

class Integer
{
    int m_value;

public :
    Integer(const int value) : 
        m_value(value)
    {
    }

    operator const int() const
    {
        return m_value;
    }

    bool operator==(const Integer& right) const
    {
        return m_value == right.m_value;
    }

    bool operator==(const int right) const
    {
        return m_value == right;
    }

    int GetValue() const
    {
        return m_value;
    }
};

bool operator==(const int left, const Integer& right)
{
    return left == right.GetValue();
}

int main()
{
    Number n1 = 1;
    Number n2 = 1;
    int x3 = 1;

    n1 == n2;
    n1 == x3; // error C2666: 'operator ==' : 3 overloads have similar conversions
    x3 == n1; // error C2666: 'operator ==' : 2 overloads have similar conversions

    Integer i4 = 1;
    Integer i5 = 1;

    i4 == i5;
    i4 == x3;
    x3 == i4;

    return 0;
}

对于类,我有两个错误,如上面的代码所示。上课一切都很好。问题是,我想在生成的类中保留单参数构造函数、强制转换运算符和相等运算(、、),但我只想在类中实现 as 的一个版本。我看不出有什么办法可以做到这一点。这是否可能,或者我必须像在课堂上一样拥有所有三个实现?我知道我为什么会遇到这些错误,我只是不喜欢我拥有的解决方案。NumberIntegerMyClass == intint == MyClassMyClass == MyClassoperator==NumberInteger

C++ 重载 类型转换运算符

评论

0赞 Nawaz 1/18/2013
请将名称更改为以避免混淆,同样,将名称更改为 和 。n3xn4n5i1i2
0赞 πάντα ῥεῖ 1/18/2013
尝试构造函数定义explicitNumber
1赞 lucasmrod 1/18/2013
一个愚蠢的解决方案:如果你去掉了,那么你想要的三种类型的比较(和)将被隐式转换为整数,它将被编译。bool operator==(const Number left, const Number right)Number == intint == NumberNumber == Number

答:

2赞 Andy Prowl 1/18/2013 #1

在类中,您定义了一个转换运算符,并且您的构造函数允许将 转换为 .因此,在比较 a 和 an 是否相等时,会出现歧义:编译器应该调用内置的 s 并转换为 ,还是应该选择运算符并转换为 ?两种转换都同样好,它不能选择一个。NumberintintNumberNumber nint xoperator ==intnintxNumber

所以是的,你必须定义三个版本,或者添加一个模板运算符,它可以完美地匹配所有参数的类型,并显式地转发给你的运算符,就像这个一样(但你很可能想用一些来保护它,以限制它的适用性,只限于适当的和):enable_ifTU

template<typename T, typename U> // beware: this will match anything. to be constrained
bool operator == (T n, U const& u)
{
    return (Number(n) == Number(u));
}

评论

0赞 Bart van Ingen Schenau 1/18/2013
这就是为什么您应该谨慎提供隐式转换的主要原因。
0赞 Pavel Dubsky 1/18/2013
我以前从未与enable_if合作过,所以我会试着弄清楚。感谢您的解决方案!
0赞 Lol4t0 1/18/2013 #2

您只能将一个定义为成员函数:operator==

bool operator==(const int& right) const
{
    std::cout << "custom\n";
    return this->GetValue() == right;
}

然后

  • n1==n2:将转换为,并且将使用自定义运算符。n2int
  • n1 == n3:将使用自定义运算符
  • n3==n1:将使用内置运算符

请注意,您希望 be 能够比较常量 soperator==constNumber

0赞 Yakk - Adam Nevraumont 1/18/2013 #3

在 C++11 中,您可以显式。operator int

另一种方法是使用 SFINAE 来获得适用于一个或多个 args 的模板,但这是使用火箭筒杀死蚂蚁。==Number