Reputation: 5523
I have a variadic template function F which must be called upon exactly two objects. Another function, called G, will therefore call F twice, once for object one and the other one for object two. G is therefore also variadic, but the problem is that the two variadic parameters packs for the two calls on F can be different, and G must know which to call upon object one and which upon object two:
template< typename ...Args>
void F(Obj obj);
template<typename ...Args1, typename ...Args2>
void G(Obj obj_1, Ojb obj_2)
{
F<Args1...>( obj_1 );
F<Args2...>( obj_2 );
}
Now if I call G, which version of F is called upon obj_1 and which upon obj_2? How can this be correctly specified when calling G?
Upvotes: 1
Views: 58
Reputation: 275230
Tags are a great plan. If you don't want to use tags, you can use lambdas.
In c++20 we can do
template<class...Args1>
auto G() {
return []<class...Args2>() {
F<Args1...>( obj_1 );
F<Args2...>( obj_2 );
};
}
now calling this is a big ugly.
G<int>().operator()<double, char>();
we can clean this up with ... tags. This also only requires c++14:
template<class T>
struct tag_t { using type=T; };
template<class T>
constexpr tag_t<T> tag{};
template<class...Args1>
auto G(tag_t<Args1>...) {
return [](auto...args2) {
F<Args1...>( obj_1 );
F<typename decltype(args2)::type...>( obj_2 );
};
}
now calling this becomes:
G(tag<int>)(tag<double>, tag<char>);
which is more fun.
Upvotes: 1
Reputation: 217085
using Tag might help here, as you cannot partial specialize function:
template <typename ... Ts>
struct Tag {};
template< typename ...Args>
void F(Obj obj) { /*...*/ }
template<typename ...Args1, typename ...Args2>
void G(Tag<Args1...>, Obj obj_1, Tag<Args2...>, Ojb obj_2)
{
F<Args1...>( obj_1 );
F<Args2...>( obj_2 );
}
Upvotes: 2