Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will the C++ Concepts TS enable multiple parameter packs?

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?

like image 645
Jared Hoberock Avatar asked Sep 23 '16 19:09

Jared Hoberock


People also ask

What is parameter pack in C++?

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.

What is Variadic template in C++?

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.

What is concept in C++ 20?

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.


Video Answer


2 Answers

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; }
};
like image 198
Luc Danton Avatar answered Nov 15 '22 14:11

Luc Danton


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.

like image 30
skypjack Avatar answered Nov 15 '22 12:11

skypjack