It's been a while that I've been doing C++ but I'm not familiar with templates.
Recently, I tried to write a class that wrap a std::vector<std::tuple<Types...>>
. This class must have member functions, and I really need to be able to iterate over the tuple. In fact, if I am able to print every element of a tuple (in the order), I would be able to do everything I need.
I found a solution using a cast, but I'm not really confident with it since it is based on a cast that I don't really like (plus, when I try to use static_cast
, it doesn't compile anymore).
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, this cast is probably a runtime-cast right ? Is there a way to do what I want without this ?
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.
We can iterate over tuples using a simple for-loop. We can do common sequence operations on tuples like indexing, slicing, concatenation, multiplication, getting the min, max value and so on.
You can loop through the list items by using a while loop. Use the len() function to determine the length of the tuple, then start at 0 and loop your way through the tuple items by refering to their indexes. Remember to increase the index by 1 after each iteration.
Method 1: Using For loop with append() method Here we will use the for loop along with the append() method. We will iterate through elements of the list and will add a tuple to the resulting list using the append() method. Example: Python3.
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 to @dyp. This uses an expansion trick from this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With