std::variant 反射。如何判断分配了哪种类型的值 std::variant?

新手上路,请多包涵

I have a class called foo_t that has a member called bar which could be any one of the types std::string , int , std::vector<double> 等。我想问 foo_t bar 已分配给哪个类型。我决定使用 std::variant

我已经写了一个解决方案,但我不确定这是否可以很好地使用 std::variant。我不确定这是否重要,但我预计未来类型列表可能会变得更大。我创建了一个枚举类来存储分配给哪个类型的 std::variant。我的第一个实现也可以在 wandbox 上使用:

 #include <iostream>
#include <variant>
#include <vector>
#include <string>

enum foo_kind_t {
  double_list,
  name_tag,
  number,
  unknown
};

template <typename val_t>
struct get_foo_kind_t {
  constexpr static foo_kind_t value = unknown;
};

template <>
struct get_foo_kind_t<int> {
  constexpr static foo_kind_t value = number;
};

template <>
struct get_foo_kind_t<std::string> {
  constexpr static foo_kind_t value = name_tag;
};

template <>
struct get_foo_kind_t<std::vector<double>> {
  constexpr static foo_kind_t value = double_list;
};

class foo_t {

public:

  foo_t(): kind(unknown) {}

  template <typename val_t>
  void assign_bar(const val_t &val) {
    static_assert(get_foo_kind_t<val_t>::value != unknown, "unsupported assignment");
    kind = get_foo_kind_t<val_t>::value;
    bar = val;
  }

  foo_kind_t get_kind() {
    return kind;
  }

  template <typename val_t>
  val_t get_bar() {
    if (get_foo_kind_t<val_t>::value != kind) {
      throw std::runtime_error("wrong kind");
    }
    return std::get<val_t>(bar);
  }

private:

  foo_kind_t kind;

  std::variant<
    int,
    std::string,
    std::vector<double>
  > bar;

};

template <typename val_t>
void print_foo(foo_t &foo) {
    std::cout << "kind: " << foo.get_kind() << std::endl;
    std::cout << "value: " << foo.get_bar<val_t>() << std::endl << std::endl;
}

int main(int, char*[]) {

    // double_list
    foo_t b;
    std::vector<double> b_val({ 1.0, 1.1, 1.2 });
    b.assign_bar(b_val);
    std::cout << "kind: " << b.get_kind() << std::endl;
    std::cout << "value: vector size: " << b.get_bar<std::vector<double>>().size() << std::endl << std::endl;

    // name_tag
    foo_t d;
    std::string d_val("name");
    d.assign_bar(d_val);
    print_foo<std::string>(d);

    // number
    foo_t c;
    int c_val = 99;
    c.assign_bar(c_val);
    print_foo<int>(c);

    // unknown
    foo_t a;
    std::cout << a.get_kind() << std::endl;

    return 0;
}

这是一个好方法吗?有没有更好的表现方式?有没有一种需要编写更少代码的方法?有没有不需要 C++17 的方法?

原文由 Hoodlum 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

使用 std::variant::index 在运行时检查存储的类型。

原文由 Hoodlum 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您只需要问“这是 X 类型的变体吗?”对于单个类型 X,那么我建议您更喜欢 std::holds_alternative 而不是 std::variant::index 因为代码行更易于阅读,并且如果变体中类型的索引发生更改,则不必更新在将来。

例子:

 if (std::holds_alternative<X>(my_variant)) {
    std::cout << "Variant is of type X" << std::endl;
}

原文由 Gabriel Devillers 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题