Fedor
Fedor

Reputation: 21231

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

Upvotes: 15

Views: 355

Answers (1)

ecatmur
ecatmur

Reputation: 157354

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.

Upvotes: 1

Related Questions