It may come in handy, maybe:
template <typename... T> using VariantVector = std::vector<boost::variant<T...>>; template <typename... T> using VectorPack = std::tuple<std::vector<T>...>; template <typename... T> VectorPack<T...> splitVectors(VariantVector<T...> const &values);
The difference with the function requested by the OP is that instead of an โerrorโ when not all types of elements are consistent, it will return a tuple of vectors (โVectorPackโ) and you can simply choose which one you want.
Demo program:
#include <boost/variant.hpp> #include <boost/variant/static_visitor.hpp> #include <tuple> #include <vector> using std::get; template <typename... T> using VariantVector = std::vector<boost::variant<T...>>; template <typename... T> using VectorPack = std::tuple<std::vector<T>...>; namespace detail { template <typename T> struct VectorSplitterMixin { void operator()(T const& v) { _bucket.push_back(v); } std::vector<T> _bucket; }; template <typename... T> struct VectorSplitter : boost::static_visitor<>, VectorSplitterMixin<T>... { typedef VectorPack<T...> product_t; product_t product() { return product_t { std::move(static_cast<VectorSplitterMixin<T>*>(this)->_bucket)... }; } }; } template <typename T> struct X; template <typename... T> VectorPack<T...> splitVectors(VariantVector<T...> const &values) { auto splitter = detail::VectorSplitter<T...>(); for (auto& val : values) boost::apply_visitor(splitter, val); return splitter.product(); } int main() { typedef boost::variant<int, std::string> Value; typedef boost::variant<std::vector<int>, std::vector<std::string> > Container; const std::vector<Value> vec { 42, "hello world", 1, -99, "more" }; auto vectorPack = splitVectors<int, std::string>(vec); for (auto i : get<0>(vectorPack)) std::cout << "int:" << i << ", "; std::cout << "\n"; for (auto& s : get<1>(vectorPack)) std::cout << "string:" << s << ", "; std::cout << "\n"; }
Print
int:42, int:1, int:-99, string:hello world, string:more,
source share