14
#include <tuple>

template<int I>
struct A {};

template<int I, typename... T>
void f(A<I>, std::tuple<T *...>) {}

template<typename... T>
void f(A<0>, std::tuple<T *...>) {}

int main()
{
    f(A<0>{}, std::tuple<char*, int*, float*>{});
}

Isn't the second overload of f more specialized? g++ 4.9.2 says that the call is ambiguous, clang 3.6.0 accepts it. Which compiler is right?

It's interesting that if you change std::tuple<T *...> to std::tuple<T...>, g++ is fine with it, which I don't understand.

cubuspl42
  • 7,833
  • 4
  • 41
  • 65

1 Answers1

5

By the current rules, the second overload is more specialized. Some specialization A<@> with a synthesized value @ cannot be matched against A<0>, but A<0> can be matched against A<I> (with I=0). This first pair's asymmetry is decisive. Whether you use T or T* as the pattern in the second parameter is irrelevant, as deduction succeeds both ways for that pair.

The bug still persists in trunk and was reported by @Barry as 67228.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • Note: The resolution CWG 1391 might make this ambiguous. I'm unsure about that though. – Columbo Aug 15 '15 at 15:11
  • Yeah the resolution isn't quite right I think. Check out bogdan's answer [here](http://stackoverflow.com/a/31735126/2069064), I think he has some good ideas of how to actually resolve the wordings. – Barry Aug 15 '15 at 15:32