You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使std::variant工具兼容继承自std::variant的自定义类型

解决C++23继承std::variant后标准工具兼容问题

在C++23中,我们可以继承std::variant来扩展功能,但标准库提供的std::variant_size、std::variant_alternative、std::is_alternative等工具默认仅支持原生std::variant类型,无法直接作用于继承后的自定义类型。要让static_assert(std::variant_size_v<State> == 2);生效,只需为自定义类型特化这些标准模板即可。

基础特化方案

针对你的State类型,直接特化相关模板:

1. 特化std::variant_size

#include <variant>

struct State : std::variant<int, float> {
    using variant::variant;
};

// 特化std::variant_size
template<>
struct std::variant_size<State> : std::variant_size<std::variant<int, float>> {};

// 特化变量模板variant_size_v
template<>
inline constexpr std::size_t std::variant_size_v<State> = std::variant_size_v<std::variant<int, float>>;

2. 特化std::variant_alternative

// 特化std::variant_alternative,支持索引访问类型
template<std::size_t I>
struct std::variant_alternative<I, State> : std::variant_alternative<I, std::variant<int, float>> {};

// 特化变量模板variant_alternative_t
template<std::size_t I>
using std::variant_alternative_t<I, State> = typename variant_alternative<I, State>::type;

3. 特化std::is_alternative

// 特化std::is_alternative,检测类型是否为变体的备选类型
template<typename T>
struct std::is_alternative<T, State> : std::is_alternative<T, std::variant<int, float>> {};

// 特化变量模板is_alternative_v
template<typename T>
inline constexpr bool std::is_alternative_v<T, State> = std::is_alternative_v<T, std::variant<int, float>>;

验证代码

添加以下静态断言验证效果:

static_assert(std::variant_size_v<State> == 2); // 正常通过
static_assert(std::is_same_v<std::variant_alternative_t<0, State>, int>);
static_assert(std::is_same_v<std::variant_alternative_t<1, State>, float>);
static_assert(std::is_alternative_v<int, State>);
static_assert(!std::is_alternative_v<double, State>);

通用特化方案(多继承类型场景)

如果有多个继承自std::variant的自定义类型,可编写通用辅助模板避免重复特化:

#include <variant>
#include <type_traits>

// 辅助模板:检测类型是否继承自std::variant
template<typename T>
struct is_variant_derived : std::false_type {};

// 匹配原生std::variant
template<typename... Ts>
struct is_variant_derived<std::variant<Ts...>> : std::true_type {};

// 匹配继承std::variant且暴露了variant别名的类型
template<typename Derived>
struct is_variant_derived<Derived> : is_variant_derived<typename Derived::variant> {};

// 通用特化std::variant_size
template<typename T>
requires is_variant_derived<T>::value
struct std::variant_size<T> : std::variant_size<typename T::variant> {};

template<typename T>
requires is_variant_derived<T>::value
inline constexpr std::size_t std::variant_size_v<T> = std::variant_size_v<typename T::variant>;

// 通用特化std::variant_alternative
template<std::size_t I, typename T>
requires is_variant_derived<T>::value
struct std::variant_alternative<I, T> : std::variant_alternative<I, typename T::variant> {};

template<std::size_t I, typename T>
requires is_variant_derived<T>::value
using std::variant_alternative_t<I, T> = typename variant_alternative<I, T>::type;

// 通用特化std::is_alternative
template<typename U, typename T>
requires is_variant_derived<T>::value
struct std::is_alternative<U, T> : std::is_alternative<U, typename T::variant> {};

template<typename U, typename T>
requires is_variant_derived<T>::value
inline constexpr bool std::is_alternative_v<U, T> = std::is_alternative_v<U, typename T::variant>;

使用时,只需在自定义类型中添加using variant = std::variant<...>;:

struct State : std::variant<int, float> {
    using variant = std::variant<int, float>; // 暴露基类型别名
    using variant::variant;
};

struct AnotherState : std::variant<std::string, bool> {
    using variant = std::variant<std::string, bool>;
    using variant::variant;
};

// 验证
static_assert(std::variant_size_v<State> == 2);
static_assert(std::variant_size_v<AnotherState> == 2);

内容的提问来源于stack exchange,提问作者Basti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:41:17