In my application I generate a tuple with many vectors holding values. I would like to have a generic way of iterating over the tuple to extract the single vector with least values.
For example:
auto t = std::make_tuple(std::vector<int>({1,2}), std::vector<double>({1.0, 2.0, 3.0}));
How do I extract the vector which holds the least values?
Let's assume we either have no duplicates in our pack of types, or a way of removing them, and also a C++11 backport of std::index_sequence
#include <map>
#include <tuple>
#include <functional>
#include <iostream>
#include <boost/variant>
#include <future/index_sequence>
namespace detail {
template<typename Variant, typename Tuple, std::size_t... Is>
std::map<std::size_t, std::function<Variant(const Tuple &)>> from_tuple_map(index_sequence<Is...>)
{
return { { Is, [](const Tuple & tup){ return std::get<Is>(tup); } }... };
}
struct GetSize
{
template<typename T>
std::size_t operator()(const std::vector<T> & vec){ return vec.size(); }
}; // becomes C++14 generic lambda
}
template<typename... Ts>
boost::variant<Ts...> from_tuple(const std::tuple<Ts...> & tup)
{
auto map = detail::from_tuple_map<boost::variant<Ts...>, std::tuple<Ts...>>(make_index_sequence<sizeof...(Ts)>());
auto get_size = GetSize{};
std::size_t best = 0;
std::size_t len = visit(get_size, map[best](tup));
for (std::size_t trial = 1; trial < sizeof...(Ts); ++trial)
{
std::size_t trial_len = visit(get_size, map[trial](tup));
if (trial_len > len)
{
best = trial;
len = trial_len;
}
}
return map[best](tup);
}
int main()
{
auto x = from_tuple(std::make_tuple(std::vector<int>({1,2}), std::vector<double>({1.0, 2.0, 3.0})));
visit([](const auto & a){ std::cout << a[1]; }, x);
}