Reputation: 25663
I have a syntax problem with expanding a tuple to its content.
The working code I have:
class Example
{
public:
static void Go( int i, float f)
{
std::cout << "p1: " << i << std::endl;
std::cout << "p2: " << f << std::endl;
}
template <typename T, size_t ... I>
static void Do( T parm )
{
Go( std::get<I>( parm)...);
}
};
int main()
{
using X = std::tuple<int, float>;
Example::Do<X,0,1>( std::make_tuple( 1,2.2)) ;
}
But I want to call the expansion with something like
int main()
{
using X = std::tuple<int, float>;
using IDX = std::std::index_sequence_for<int, float>;
Example::Do<X,IDX>( std::make_tuple( 1,2.2)) ;
}
So I am searching for something like ( which can not compiled... ):
template <typename T, size_t ... I>
static void Do<T, std::index_sequence<I...>>(T parm)
{
Go( std::get<I>( parm)...);
}
Upvotes: 1
Views: 373
Reputation: 37661
The problem is that your std::index_sequence
(IDX
) is not expanding in the template parameters to what you need:
Example::Do<X, IDX>(std::make_tuple(1, 2.2));
...will not "expand" to:
Example::Do<X, 0, 1>(std::make_tuple(1, 2.2)); // This works
What you need is to let the compiler deduce the template arguments for ...I
, to do so change your static method to:
template <typename T, size_t ... I>
static void Do(T parm, std::index_sequence<I...>)
{
Go(std::get<I>(parm)...);
}
And then call it with:
Example::Do(std::make_tuple(1, 2.2), IDX{});
The compiler will automatically deduce the template arguments and call Example::Do<X, 0, 1>
as needed.
If you want to be able to call Do
without the second arguments, you can add another layer of abstraction in Example
:
class Example
{
public:
static void Go(int i, float f) {
std::cout << "p1: " << i << std::endl;
std::cout << "p2: " << f << std::endl;
}
template <typename Tuple>
static void Do(Tuple &&parm) {
_Do(std::forward<Tuple>(parm),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>{}>{});
}
private:
template <typename Tuple, size_t... I>
static void _Do(Tuple &&parm, std::index_sequence<I...>) {
Go(std::get<I>(std::forward<Tuple>(parm))...);
}
};
Then:
Example::Do(std::make_tuple(1, 2.2));
Note that the three versions:
Example::Do<X, 0, 1> (std::make_tuple(1, 2.2));
Example::Do(std::make_tuple(1, 2.2), IDX{});
Example::Do(std::make_tuple(1, 2.2));
Will likely results in the same code after compiler optimization (on my machine with clang++-3.7
and -O1
, the three assembly files are strictly identical).
Upvotes: 1
Reputation: 93364
Pass the index sequence by value:
template <typename T, size_t... I>
static void Do(T parm, std::index_sequence<I...>)
{
Go(std::get<I>(parm)...);
}
Call the method like this:
Example::Do(std::make_tuple(1, 2.2),
std::index_sequence_for<int, float>{});
Upvotes: 1