BOOST_STRONG_TYPEDEF和重载关系操作符

BOOST_STRONG_TYPEDEF and overloaded relational operators

本文关键字:关系 操作符 重载 TYPEDEF STRONG BOOST      更新时间:2023-10-16

我使用BOOstrongTRONG_TYPEDEF从POD类型定义强类型。例如,我想从int定义一个新类型。然而,如果我试图将我的新类型与int以外的东西进行比较(例如unsigned int, size_t),我会得到"使用重载操作符'<'是模棱两可的"编译器错误。

例如:

#include <boost/serialization/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF( int, Foo );
int main(int argc, const char * argv[]) {
    Foo f( 10 );
    unsigned int j = 11;
    bool result = j < f;    // Error
    size_t s = 100;
    result = s < f;         // Error
    int h = 101;
    result =  h < f;        // ok
    return 0;
}

可以通过为特定类型实现特定的关系操作符来修复这些错误。例如:

bool operator<(const size_t& y, const Foo& x) {
    return y < x.t;
}

由于BOOstrongTRONG_TYPEDEF提供了从Fooint的转换操作符,我希望(unsigned int) < (Foo)编译成与(unsigned int) < (int)相同的东西,但我猜不是。

我的问题是:是否有任何方法可以避免为我想比较的每种类型实现每个操作符?

由于BOOstrongTRONG_TYPEDEF提供了从Fooint的转换操作符,我希望(unsigned int) < (Foo)编译成与(unsigned int) < (int)相同的东西,但我猜不是。

BOOST_STRONG_TYPEDEF宏定义了一个struct Foo,它继承了一堆不同的操作符类,其中一个将定义:

friend bool operator<(const int&, const Foo&); //(1)

当然还有很多内置的比较整数的程序:

bool operator<(T, U); // (2), implicit

对于所有的整型,I,我们有几个可行的候选I{} < Foo{}。我们可以将I转换为int并调用(1),或者将Foo转换为int并调用(2)。根据I,结果是:

  • Iint: (1)是一个精确匹配,并且所有内置操作符都涉及转换,因此(1)无疑是首选。
  • I具有低于int(例如char)的级别:积分提升(直到int)具有比转换(Fooint)更高的级别,因此(1)无疑是首选。
  • I具有高于int排名(例如,size_tunsigned int在您的示例中):(1)现在涉及整数转换(size_tint不是提升),整数转换具有排名转换,与用户自定义转换相同的排名。所以(1)(2)都有一个精确匹配和一个转换。因为哪一个都不比另一个好,所以它是模棱两可的。

我的问题是:是否有任何方法可以避免为我想比较的每种类型实现每个操作符?

不,没有。但是,您可以使用模板一次性实现每种类型的每个操作符。例如,我们可以用:

来解决<的所有歧义。
template <typename T>
bool operator<(const T& t, const Foo& f)
{
    return t < static_cast<int>(f);
}

对于秩为int的整型,仍然优先选择(1)。但是对于所有其他整型,模板将是精确匹配的,而内置和(1)涉及一些转换序列,因此这将是首选-这将转发到一个模棱两可的内置。