【问题标题】:Compare std::variant with int using C++20 <=> is not a constant expression使用 C++20 将 std::variant 与 int 进行比较 <=> 不是常量表达式
【发布时间】:2020-11-26 08:46:07
【问题描述】:

由于 std::variant 不允许与标准库中的其中一种替代类型进行比较,我正在使用 C++20 &lt;=&gt; 运算符实现比较函数:

template <typename... Args, typename T>
constexpr auto operator<=>(const std::variant<Args...>& v, const T& t) {
  return std::visit([&t](const auto& u) -> std::partial_ordering {
    if constexpr (requires { u <=> t; }) return u <=> t;
    else return std::partial_ordering::unordered;
  }, v);
}

但是当我用自己定义的std::variant测试上述函数时:

using Variant = std::variant<double, int, std::string_view>;
constexpr Variant v1{1.0};
constexpr Variant v2{1};
constexpr Variant v3{"hello"};
static_assert(v1 < 2);
// compile error
static_assert(v2 < 2);
static_assert(!(v3 > 2) && !(v3 < 2) && !std::is_eq(v3 <=> 2));

The second assertion couldn't compile,GCC 说:

<source>:19:17: error: non-constant condition for static assertion
   19 |   static_assert(v2 < 2);
      |                 ^~~~~~~~~
<source>:19:24:   in 'constexpr' expansion of 'operator<=><double, int, std::basic_string_view<char, std::char_traits<char> >, int>(v2, 2)'
<source>:19:17: error: '<anonymous>' is not a constant expression

为什么v2 &lt; 2 不是常量表达式?或者它只是一个 GCC 错误?更奇怪的是,当我将第二个断言更改为与double 进行比较时,这可以编译:

static_assert(v2 < 2.0);

更新:

Clang can pass three assertions, but MSVC can only pass the third assertion,看来MSVC也有bug。

【问题讨论】:

  • 第一个示例是编译器错误。第二个示例格式不正确(您的 visit lambda 针对不同的调用返回不同的类型),尽管仍然是 ICE-ing 的 gcc 错误(ICE 始终是错误)。

标签: c++ c++17 c++20 std-variant


【解决方案1】:

第一个例子简化为:

#include <compare>

// this one is okay
static_assert(std::partial_ordering(std::strong_ordering::less) < 0);

// this one fails with non-constant condition
static_assert(std::partial_ordering(1 <=> 2) < 0);

这里的一切显然都是一个常量表达式。 strong_ordering::less 可以转换为 partial_ordering::less 就好了,而 1 &lt;=&gt; 2 不能(在 gcc 上)这一事实表明这是编译器中的错误,而不是库中的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-02
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 2022-11-28
    • 1970-01-01
    相关资源
    最近更新 更多