plasmacel
plasmacel

Reputation: 8539

Variadic template constructor priority

Given the following simple struct

template <typename T>
struct A
{
   A(T a) {}

   template <typename ... Ts>
   A(T a, Ts ... more) {}
};

int main()
{
   A<int> a(1);
}

What is the guarantee that A(T a) will be called instead of the variadic template constructor, and why?

Upvotes: 5

Views: 401

Answers (2)

Richard Hodges
Richard Hodges

Reputation: 69902

The section in the standard you're looking for is §14.8.2.4

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails. Otherwise, using the resulting types P and A, the deduction is then done as described in 14.8.2.5. If P is a function parameter pack, the type A of each remaining parameter type of the argument template is compared with the type P of the declarator-id of the function parameter pack. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template.

[ Example:

template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more
// specialized than the variadic templates #1 and #2

— end example ]

Upvotes: 6

aschepler
aschepler

Reputation: 72431

The same reason f(const int&) is a better match than f(const T&) when T can be deduced as int: A(int) is a non-template function and A(int, Ts...) with Ts... deduced as the empty list is a function template specialization.

Upvotes: 2

Related Questions