Iterate on a tuple ... again

Some time passed when I was doing C ++, but I am not familiar with templates.

I recently tried to write a class that wrapped std::vector<std::tuple<Types...>> . This class must have member functions, and I really need to be able to iterate through the tuple. In fact, if I can print each element of the tuple (in order), I could do whatever I need.

I found a solution using the cast, but I'm not sure about this, since it is based on an actor that I don't really like (plus, when I try to use static_cast , it does not compile).

My question is, is the following code correct, portable, is it a hack, and should I find another way to do this than to use this cast? Also, is this actor probably right to perform at runtime? Is there a way to do what I want without it?

 std::ostream& operator<<(std::ostream& out, std::tuple<> const& tuple) { return out; // Nothing to do here } template<typename First, typename... Types> std::ostream& operator<<(std::ostream& out, std::tuple<First, Types...> const& tuple) { out << std::get<0>(tuple) << " "; // The cast that I don't like return out << (std::tuple<Types...>&) tuple; } int main() { auto tuple = std::make_tuple(1, 2.3, "Hello"); std::cout << tuple << std::endl; return 0; } 

Thank you in advance for your answers.

+8
c ++ templates c ++ 14 variadic-templates
source share
2 answers

Use std::index_sequence_for for fun and profit.

 template <typename TupleLike, size_t ... Inds> std::ostream& PrintHelper(std::ostream& out, TupleLike const& tuple, std::index_sequence<Inds...>) { int unused[] = {0, (void(out << std::get<Inds>(tuple) << " "), 0)...}; (void)unused; return out; } template<typename... Types> std::ostream& operator<<(std::ostream& out, std::tuple<Types...> const& tuple) { return PrintHelper(out, tuple, std::index_sequence_for<Types...>()); } 

EDIT: Live Demo . Thanks @dyp. It uses the extension trick from this answer .

+10
source share

I found another way to do what I want. I used this article , which can print the elements of a tuple in descending order, and I use the second index J == std::tuple_size<std::tuple<Types...>>::value - I , so I can specialize the template, if I==0 .

 template<std::size_t I, std::size_t J, typename... Types> struct printHelper { std::ostream& operator()(std::ostream& out, std::tuple<Types...> const& tuple) { out << std::get<J>(tuple) << " "; // Recursive call without cast return printHelper<I-1,J+1,Types...>{}(out, tuple); }; }; // Specialization on the last element when I==0 template<std::size_t J, typename... Types> struct printHelper<0,J,Types...> { std::ostream& operator()(std::ostream& out, std::tuple<Types...> const& tuple) { // Nothing to do here return out; } }; template<typename... Types> std::ostream& operator<<(std::ostream& out, std::tuple<Types...> const& tuple) { return printHelper<std::tuple_size<std::tuple<Types...>>::value, 0, Types...>{}(out, tuple); } 
0
source share

All Articles