Home > Blockchain >  Why std::tuple comparison calls operator bool when operator< overload is provided
Why std::tuple comparison calls operator bool when operator< overload is provided

Time:02-03

#include <tuple>

struct X {
    int i = 0;
    friend constexpr bool operator<(const X &l, const X &r) noexcept {
        return l.i < r.i;
    }
};

struct Y {
    int i = 0;
    constexpr operator bool() const noexcept {
        return i != 0;
    }
    friend constexpr bool operator<(const Y &l, const Y &r) noexcept {
        return l.i < r.i;
    }
};

int main() {
    constexpr X a{1}, b{2};
    static_assert(std::tie(a) < std::tie(b));

    constexpr Y c{1}, d{2};
    static_assert(c < d);
    // assert failed
    // static_assert(std::tie(c) < std::tie(d));

    return 0;
}

Updating: When compiling with C 20.

Line static_assert(std::tie(c) < std::tie(d)); will fail. It turns out that when comparing c and d, operator bool is called instead of operator<. Why would operator bool get involved in the first place?

I find this quite surprising. Is this intended or a bug? Any help is welcome, thanks.

CodePudding user response:

When comparing two tuple<T>s, named t1 and t2, the operator<=> overload for tuple will use get<0>(t1) <=> get<0>(t2) to compare elements when type T satisfies three_­way_­comparable; otherwise, it will use operator<.

Since Y is implicitly convertible to bool, this makes y <=> y a valid expression and satisfies three_­way_­comparable, such that std::tie(c) < std::tie(d) (unexpectedly) invokes bool(c) <=> bool(d) in your example.

  • Related