我需要以(名称,值)的形式存储一系列数据点,其中值可以采用不同的类型。
我正在尝试为每个数据点使用一个类模板。然后对于我看到的每个数据点,我想创建一个新对象并将其推回向量中。对于每种新类型,我需要先从模板创建一个新类。但是我不能存储在任何向量中创建的对象,因为向量期望所有条目的类型相同。我需要存储的类型不能适合继承层次结构。他们是无关的。将来还会创建更多类型,我不想为每种新类型更改存储服务。有没有办法创建一个异构容器来存储这些条目?谢谢!
我需要以(名称,值)的形式存储一系列数据点,其中值可以采用不同的类型。
我正在尝试为每个数据点使用一个类模板。然后对于我看到的每个数据点,我想创建一个新对象并将其推回向量中。对于每种新类型,我需要先从模板创建一个新类。但是我不能存储在任何向量中创建的对象,因为向量期望所有条目的类型相同。我需要存储的类型不能适合继承层次结构。他们是无关的。将来还会创建更多类型,我不想为每种新类型更改存储服务。有没有办法创建一个异构容器来存储这些条目?谢谢!
std::any
允许保存任何类型,尽管它需要知道存储的类型才能检索它。
但是,如果您有一组已知类型,您可能更喜欢std::variant
:
using variant_type = std::variant<Foo, Bar, Joe>;
int func(variant_type const& v) // not template
{
auto const visitor = [](auto const& t)
{
if constexpr (std::is_same_v<Foo const&, decltype(t)>)
{
return t.fooish();
}
else
{
return t.barjoeish();
}
};
return std::visit(visitor, v);
}
快速定义访问者的有用技巧:
template <typename... Ts> struct overload : Ts...
{
overload(Ts... aFns) : Ts(aFns)... {}
using Ts::operator()...;
};
template <typename... Ts> overload(Ts...) -> overload<Ts...>;
// Used as
auto const visitor = overload(
[](Foo const& foo) { return foo.fooish(); },
[](auto const& other) { return other.joebarish(); }
);
return std::visit(visitor, variant);
boost::any
已经被推荐了,但是它适用于任何东西,所以你不能期望太多。
如果您提前知道各种类型,则最好使用boost::variant
.
typedef boost::variant<Foo, Bar, Joe> variant_type;
struct Print: boost::static_visitor<>
{
void operator()(Foo const& f) const { f.print(std::cout); }
template <class T>
void operator()(T const& t) const { std::cout << t << '\n'; }
};
void func(variant_type const& v) // not template
{
boost::apply_visitor(Print(), v); // compile-time checking
// that all types are handled
}
boost 库可能有你正在寻找的东西(boost::any)。如果您不能使用 boost,您可以使用包装指针方法自行滚动...
像这样的容器的问题在于,当您想要访问容器中的某些内容时,您必须确定其类型,然后以某种方式将其转换为实际类型。这是丑陋、低效且容易出错的,这就是为什么 C++ 中的第一选择是使用继承,除非你有充分的理由不这样做——这是我在 C++ 职业生涯中从未真正遇到过的。
我在想您可以只拥有一个 Pair(type, void*) 并编写自己的 pop 函数,该函数根据对中描述的类型投射 void* ,然后将它们推入任何吸引您眼球的容器中。