Reputation:
template <class... T_values>
class Thing {
public:
void something(T_values... values) {
tuple_ = std::tuple<T_values...>(values...);
}
void do_something_with_values() {
call_yadda_with_tuple(tuple_,
std::index_sequence_for<T_value...>())
}
void yadda(T... values);
private:
//The helper method.
template<std::size_t... Is>
void call_yadda_with_tuple(const std::tuple<T_values...>& tuple,
std::index_sequence<Is...>) {
yadda(std::get<Is>(tuple)...);
}
std::tuple<T_values...> tuple_;
};
Above sourcecode comes from: https://www.murrayc.com/permalink/2015/12/05/modern-c-variadic-template-parameters-and-tuples/
I would like to ask some questions:
std::index_sequence_for<T_value...>())
?yadda(std::get<Is>(tuple)...);
there is Is
instead of Is...
? Therefore, what does it mean Is
? Is...
in unpacked ( expanded ) types pack but what is Is
. std::get
fits from (1)-(8)
(http://en.cppreference.com/w/cpp/utility/tuple/get)call_yadda_with_tuple
gets std::index_sequence<Is...>
.
After all, this argument is nameless so it is useless. I suppose that it is connected with deduction types but I cannot see how does it help?Upvotes: 0
Views: 108
Reputation: 69902
What does return std::index_sequence_for()) ?
assuming T_value... is T, T, T (i.e. 3 types...)
std::index_sequence<0, 1, 2>
Why in yadda(std::get(tuple)...); there is Is instead of Is...? Therefore, what does it mean Is? Is... in unpacked ( expanded ) types pack but what is Is.
Is
represents 'the current value of Is' while Is...
is being unpacked. The trailing ...
causes unpacking of the expression in which Is
is used.
Especially, which std::get fits from (1)-(8) (http://en.cppreference.com/w/cpp/utility/tuple/get)
In this case the tuple reference is a const std::tuple<T_values...>&
so it'll be number 3.
Why call_yadda_with_tuple gets std::index_sequence. After all, this argument is nameless so it is useless. I suppose that it is connected with deduction types but I cannot see how does it help?
It's there simply to cause Is...
to exist and therefore allow you to expand across all Is
in the sequence.
edit:
Here's an example with comments that hopefully explain what's going on
#include <utility>
#include <tuple>
#include <string>
#include <iostream>
// for any value I, write a comma and space to stdout
// (i.e. ignore the value I)
template<std::size_t I>
void emit_sep()
{
std::cout << ", ";
}
// specialise for when I is zero... no comma in this case
template<>
void emit_sep<0>()
{
}
// emit and value at some position I. Use emit_sep<I> to determine whether
// to print a separator
template<std::size_t I, class T>
void emit(const T& t)
{
emit_sep<I>();
std::cout << t;
}
// given a tuple type and a sequence of integers (Is...) emit the value
// at each index position of the tuple. Take care to emit a separator only
// before each element after the first one
template<class Tuple, size_t...Is>
void impl_show_it(const Tuple& tup, std::index_sequence<Is...>)
{
using expand = int[];
std::cout << "here are the indexes in the index_sequence: ";
// the following line will expand (in our example) to:
// void(int[] { 0,
// (emit<0>(0), 0),
// (emit<1>(1), 0),
// (emit<2>(2), 0),
// });
// and the optimiser will remove the operations which have no observable
// side-effects (namely, building an array of ints which is never used)
// so the code emitted will be equivalent to:
// emit<0>(0); emit<1>(1); emit<2>(2);
//
void(expand {
0,
(emit<Is>(Is), 0)...
});
std::cout << std::endl;
std::cout << "here are the values in the tuple: ";
void(expand {
0,
(emit<Is>(std::get<Is>(tup)), 0)...
});
std::cout << std::endl;
}
// for some tuple type, compute the size of the tuple, build an index sequence
// representing each INDEX in the tuple and then use that sequence to call
// impl_show_it in order to actually perform the write
template<class Tuple>
void show_it(const Tuple& tup)
{
constexpr auto tuple_size = std::tuple_size<Tuple>::value;
auto sequence = std::make_index_sequence<tuple_size>();
impl_show_it(tup, sequence);
}
// make a tuple and then show it on stdout
int main()
{
auto t = std::make_tuple(6, std::string("hello"), 5.5);
show_it(t);
}
expected results:
here are the indexes in the index_sequence: 0, 1, 2
here are the values in the tuple: 6, hello, 5.5
Upvotes: 2