使用时我看到了一些意外行为std::variant::operator<
。在类型具有隐式 bool 转换运算符并且其 less 运算符不是成员函数的情况下(在带有 mscv 19.38 编译器的 C++20 中)。
#include <variant>
struct Foo {
int x;
int y;
#ifndef DROP_CAST_OP
constexpr operator bool() const { return x || y; }
#endif
#ifdef USE_SPACESHIP
constexpr auto operator<=>(const Foo&) const noexcept = default;
#else
friend constexpr bool operator<(const Foo& a, const Foo& b) noexcept
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
#endif
};
using TestVariant = std::variant<Foo, int>;
constexpr Foo fooA { 0, 1 };
constexpr Foo fooB { 1, 0 };
constexpr std::variant<Foo, int> varA = fooA;
constexpr std::variant<Foo, int> varB = fooB;
static_assert(fooA < fooB);
static_assert(varA < varB);
https://godbolt.org/z/1zfq5dq1r
请注意,当满足以下条件之一时,断言开始通过:
- 使用 C++17 代替 C++20
- 使用三向比较运算符代替自由函数运算符
- 未定义隐式转换为 bool 运算符
- 将转换 bool 运算符标记为显式
所有编译器都有相同的行为。