c++ - Compare std::variant with int using C++20 <=> is not a constant expression
问题描述
Since the std::variant
is not allowed to compare with one of its alternative types in the standard library, I am implementing the compare function using C++20 <=>
operator:
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);
}
But when I testing the above function with my own defined 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 says:
<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
Why is v2 < 2
not a constant expression? or it's just a GCC bug? Weirder, when I change the second assertion to compare with double
, this can compile:
static_assert(v2 < 2.0);
Update:
Clang can pass three assertions, but MSVC can only pass the third assertion, it seems MSVC also has a bug.
解决方案
The first example reduces to:
#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);
Everything here is obviously a constant expression. The fact that strong_ordering::less
can be converted to partial_ordering::less
just fine while 1 <=> 2
can't be (on gcc) suggests that this is a bug in the compiler, rather than the library.
推荐阅读
- java - 在另一个类上调用 get 方法时获取空数据
- docker - 如何在 docker 主机和 docker 容器之间共享端口 8080 而不会发生端口冲突?
- powershell - 使用 PowerShell 将服务总线队列消息内容转换为字符串
- php - 如何忽略库中的主要自动递增列 (ifsnop / mysqldump-php)
- json - .NET CORE 3.1 Razor 页面调用 API 在 IIS 服务器上不返回任何内容 在本地返回数据
- jquery - Laravel 7 Ajax 请求变量为空
- maven - 如何定义 Maven 的环境变量来定义本地存储库和包装器下载位置?
- css - 使用shape-outside包装时如何将img与文本底部对齐
- google-bigquery - Python Beam Airflow 未创建 BigQuery 分区表
- video.js - 如何在视频播放器之外显示 video.js 控件