我有一个名为foo_t
的类,其中有一个成员叫做bar
,它可以是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的方法?
foo_t
的节点,每个节点都包含自己的 0 个或多个子节点,这些子节点也是类型为foo_t
的。我想在遍历此树的同时,基于这些节点绘制用户界面。我知道我可以使用访问者模式来实现,但我仍然希望能够动态获取类型。 - Hoodlumstd::variant::index
- Justin