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

C++17中如何从<TYPE,INT>参数包提取TYPE并传给std::variant作为基类?

在C++17中实现Foo继承std::variant并提取参数包中的类型

完全可以实现。核心思路是利用C++17的参数包展开特性,将每个P的type成员提取出来,作为std::variant的模板参数。

修改后的完整代码如下:

#include <variant>
#include <iostream>
#include <type_traits>

template <typename T, int I>
struct Type {
  using type = T;
  static constexpr int value = I;
};

template <typename ...P>
struct Foo : std::variant<typename P::type...> {
  // 继承std::variant的所有构造函数
  using std::variant<typename P::type...>::variant;

  int index = 0;

  template <typename T, std::enable_if_t<(std::is_same_v<T, typename P::type> || ...), std::nullptr_t> = nullptr>
  Foo& operator=(const T& val) {
    // 先调用std::variant的赋值,更新内部值
    static_cast<std::variant<typename P::type...>&>(*this) = val;
    // 匹配对应的类型并设置index
    (void)((std::is_same_v<T, typename P::type> ? (index = P::value, true) : false) || ...);
    return *this;
  }
};

int main() {
  Foo<Type<int, 10>, Type<float, 20>> x;
  
  x = 42;
  std::cout << x.index << '\n'; // 输出10
  std::cout << std::get<int>(x) << '\n'; // 输出42
  
  x = 42.f;
  std::cout << x.index << '\n'; // 输出20
  std::cout << std::get<float>(x) << '\n'; // 输出42
  
  // x = 42L; // 编译错误,符合预期
}

关键说明

  1. 参数包展开:std::variant<typename P::type...>会将模板参数包P中的每个元素,提取其type成员,最终展开成std::variant<int, float>(对应示例中的参数)。
  2. 构造函数继承:通过using std::variant<...>::variant;继承std::variant的所有构造函数,确保Foo可以像普通std::variant一样初始化(比如直接用int或float值构造)。
  3. 赋值操作增强:在自定义的operator=中,先调用基类std::variant的赋值操作更新内部存储的值,再匹配类型设置index,保证两者状态一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:39:22