In C++14, it is not possible to call a function template with multiple parameter packs:
#include <future>
template<class... Futures, class... Incrementables>
void foo(Futures&... futures, Incrementables... incrementables)
{
}
int main()
{
std::future<int> a, b;
int x, y;
// ERROR
foo(a, b, x, y);
return 0;
}
Because it's not clear where the first parameter pack ends and the second one begins, it's not possible to call foo
without additional information provided by the programmer.
However, it seems like the two parameter packs could be disambiguated in principle, given proper Concepts for Future
and Incrementable
.
Will any features of the upcoming C++ Concepts Technical Specification relax these restrictions and allow calling a function template with more than one parameter pack?
Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.
Concepts are an extension to the templates feature provided by the C++ programming language. Concepts are named Boolean predicates on template parameters, evaluated at compile time.
The constraint system of Concepts Lite sits on top of the existing template machinery. In particular, it does not interfere with template argument deduction. The Futures
pack is non-deducible in your example, and will remain so even with concepts.
However, it seems like the two parameter packs could be disambiguated in principle, given proper Concepts for Future and Incrementable.
You may not have picked the best example here, although that doesn't really make the premise of your question any less interesting. What do you make of this?
Future{Fut}
struct incrementable_future: Fut {
using Fut::Fut;
incrementable_future& operator++() { return *this; }
};
In C++14, it is not possible to call a function template with multiple parameter packs
As mentioned in the comments to the question, it's possible even in C++14, as long as those packs can be deduced.
It follows a minimal, working example:
#include <tuple>
#include<functional>
template<class... T, std::size_t... I, typename... U>
void foo(std::tuple<T...> ts, std::index_sequence<I...>, std::tuple<U...> us)
{ }
int main() {
foo(std::make_tuple(42, 'b'), std::make_index_sequence<10>(), std::make_tuple(0., 'c'));
return 0;
}
Another way to do that is by means of template specializations:
template<typename, typename>
struct S;
template<typename R1, typename... A1, typename R2, typename... A2>
struct S <R1(A1...), R2(A2...)> {};
int main() {
S<void(int, char), int(char, float, double)> s;
}
And here is a third example that doesn't require a std::tuple
or some other artifact:
template<typename... A, typename... B>
void f(B...) { }
int main() {
f<int, char>(42, 0.);
}
Here the trick is in the fact that the parameter pack A
is explicitly specified at the function call, while the parameter pack B
is deduced from the function arguments.
This shows that you can easily provide more than one parameter pack even using C++11, no need to wait for concepts for that.
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