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);
Pre-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
}