为何无法通过constexpr/consteval函数获取constexpr std::variant的值?
问题原因与解决方法
核心原因
直接在f()里调用std::get<v.index()>(v)能正常编译,但放到constexpr/consteval函数里就报错,问题出在函数形参的常量性限制:
- 局部的
constexpr变量v,编译器能明确它的index()是编译期常量,因此可以作为std::get的模板参数。 - 但函数形参
a_variant属于运行期上下文(哪怕传入的是constexpr变量),编译器无法在函数模板实例化阶段确定a_variant.index()是固定的编译期值,而std::get的模板参数必须是编译期常量,因此触发报错。
编译报错原文:
... error: 'a_variant' is not a constant expression
7 | return std::get<a_variant.index()>(a_variant); ...
修复方案
方案1:将index作为非类型模板参数传递
把编译期确定的index显式传入函数模板,让编译器能确定std::get的模板参数:
#include <type_traits> #include <variant> template<std::size_t Idx> constexpr auto f2(const auto& a_variant) { return std::get<Idx>(a_variant); } template<std::size_t Idx> consteval auto f3(const auto& a_variant) { return std::get<Idx>(a_variant); } void f() { constexpr auto v = std::variant<int, double>{1}; constexpr auto idx = v.index(); // 现在可正常编译 [[maybe_unused]] constexpr auto r2 = f2<idx>(v); [[maybe_unused]] constexpr auto r3 = f3<idx>(v); }
方案2:按类型获取值(已知存储类型时)
如果明确variant中存储的类型,可以直接按类型调用std::get,不需要依赖index:
consteval auto f3(const auto& a_variant) { return std::get<int>(a_variant); }
方案3:C++23 constexpr if遍历所有可能类型
如果需要自动适配variant的所有替代类型,可结合std::variant_size_v和constexpr if遍历:
#include <type_traits> #include <variant> consteval auto f3(const auto& a_variant) { using VarT = decltype(a_variant); constexpr auto size = std::variant_size_v<VarT>; auto get_val = [&]<std::size_t... Idxs>(std::index_sequence<Idxs...>) { return (std::integral_constant<std::size_t, Idxs>{} == a_variant.index() ? std::get<Idxs>(a_variant) : 0)...; }; return get_val(std::make_index_sequence<size>{}); } void f() { constexpr auto v = std::variant<int, double>{1}; [[maybe_unused]] constexpr auto r3 = f3(v); // 正常编译,返回1 }
内容的提问来源于stack exchange,提问作者std_unordered_map
相关产品推荐
相关产品推荐

