简体   繁体   中英

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM