简体   繁体   中英

Overload resolution for a function with multiple parameter packs in C++

A C++ function can have more than one parameter packs. Although it does not look very practical thing, it is still interesting to know language rules about them.

For example, in case of two overloads:

constexpr int f(auto...) { return 1; }
constexpr int f(auto..., auto...) { return 2; }

Calling f with no arguments f() selects version 1 in MSVC, version 2 in Clang, and ambiguous overloaded call in GCC.

If call f with an argument f(1) , then both MSVC and GCC select version 1, while Clang still selects version 2.

Demo: https://gcc.godbolt.org/z/PWr6h1dn1

Which compiler is right here?

There is a similar question Function template overload resolution with two parameter packs , but

  • the functions there have only one parameter pack as function argument (and the second parameter pack is simply unused),
  • the example there results in ambiguity error in all tested compilers (however mentioned compiler bugs are still not resolved). Actually an ambiguity is what one could expect in this example as well, but here most compilers select one of the overloads without an error.

This should result in the program being rejected as ambiguous, in both cases.

Firstly note that :

In the context of a function call, the types used are those function parameter types for which the function call has arguments.

That is, only the actual arguments provided contribute to function template partial ordering. So the presence of a preceding function parameter pack in (2) does not contribute to the process of deduction of one function template against the other; it is deduced as empty and does not contribute further.

Now, the tiebreaker for partial ordering with trailing packs can't help , since both have a trailing pack:

[...] if G has a trailing function parameter pack for which F does not have a corresponding parameter, and if F does not have a trailing function parameter pack, then F is more specialized than G .

But both have a trailing parameter pack, and it is of the same length, so the language on "for which F does not have a corresponding parameter" (which is admittedly not entirely clear; see CWG 1395 ) doesn't help either.

I think that if template arguments are provided (and they are those that would be deduced), then (2) should be preferred, since in that case its trailing function parameter pack will be shorter. But this is very much not clear; clang agrees with me, but gcc and MSVC take the opposite course.

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