C++17 及更高版本。
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);
C++17 之前的版本。
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
}