Reputation: 7830
I have a function which looks somewhat like this:
template <typename... A, typename... B>
void foo(Foo<A...>&, Foo<B...>&);
The problem is, I want it to accept any types of references (lvalue/rvalue) in both const/non-const versions for both arguments.
That's already 16 combinations, and obviously it's too many to write them manually.
The only solution I could see is to drop the nested type parameters:
template <typename X, typename Y>
void foo(X&&, Y&&);
// + some SFINAE to enforce that X, Y are Foo-s
This is not acceptable, because I do need to know these nested types A...
and B...
. What should I do?
Upvotes: 2
Views: 128
Reputation: 48487
You can accept arguments by taking forwarding-references and pass their types separately, wrapped in a helper type, tag
.
#include <type_traits>
#include <utility>
template <typename> struct tag {};
template <typename X, typename Y, typename... A, typename... B>
void foo(X&& x, Y&& y, tag<Foo<A...>>, tag<Foo<B...>>)
{
// handle x and y
}
template <typename X, typename Y>
void foo(X&& x, Y&& y)
{
return foo(std::forward<X>(x), std::forward<Y>(y)
, tag<typename std::decay<X>::type>{}
, tag<typename std::decay<Y>::type>{});
}
Upvotes: 6