Deduction guides and variadic class templates with variadic template constructors - mismatched argument pack lengths

To simplify your example further, it appears that GCC does not implement variadic template arguments in deduction guides:

https://wandbox.org/permlink/4YsacnW9wYcoceDH

I didn't see any explicit mention of variadic templates in the wording for deduction guides in the standard or on cppreference.com. I see no interpretation of the standard that disallows this. Therefore I think this is a bug.


Since foo has a constructor the compiler generates an implicit deduction guide based on the constructor:

// implicitly generated from foo<T...>::foo<U...>(U...)
template<class... T, class... U> foo(U...) -> foo<T...>;

template<class... T> foo(T...) -> foo<T...>; // explicit

The problem then is that gcc is preferring the implicit guide, and thus deducing T to {} and U to {bar}; clang (since 5.0.0 according to godbolt) prefers the explicit guide. This is an overload resolution problem; when two deduction guides are found to be ambiguous, explicit deduction guides are preferred over implicit deduction guides. But clang and gcc disagree over whether the deduction guides are ambiguous:

template<class... T, class... U> int f(U...) { return 1; }
template<class... T> int f(T...) { return 2; }
int i = f(1, 2);

This program (not involving deduction guides at all) is accepted by gcc (selecting #1) and rejected by clang (as ambiguous). Retracing our steps, this means that going back to deduction guides clang gets to tie-break the ambiguity by selecting the explicit deduction guide over the implicit deduction guide (generated from the constructor template), while gcc cannot do this as it has already selected the implicit deduction guide as a preferred candidate.

We can construct an even simpler example:

template<class... T, int = 0> int f(T...);  // #1
template<class... T> int f(T...);  // #2
int i = f(1, 2);

Again, gcc (incorrectly) selects #1 while clang rejects as ambiguous.

Importantly, we can workaround this issue by adding another explicit deduction guide that gcc will nevertheless prefer to the implicit deduction guide generated from the constructor:

template <typename U, typename... Us>
foo(U&& u, Us&&... us) -> foo<U, Us...>;

This is preferred (when more than 0 arguments are supplied) since it is binding the first argument to a singular parameter as opposed to a pack. In the 0-argument case it does not matter which deduction guide (between the original explicit guide and the implicitly generated guide) is selected since both come up with the same result, foo<>. It is safe to add this for all compilers, since it is preferred in the 1+-argument case and is not a candidate in the 0-argument case.

Example.