2

In the following program there are

  • struct A<int> template, and
  • function template f<I> having const int& template argument, and A<I> function argument:
template<int>
struct A {};

template<const int & I>
void f(A<I>) {}
 
int main() {
    const static int a = 0;
    f<a>(A<a>{}); // ok in GCC and Clang
    f(A<a>{});    // ok in GCC
}

The function can be called explicitly specifying template argument <a> in GCC and Clang.

But auto-deduction of template argument works only in GCC, while Clang complains:

error: no matching function for call to 'f'
note: candidate template ignored: could not match 'const int' against 'int'

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

Which compiler is right here?

Fedor
  • 17,146
  • 13
  • 40
  • 131

1 Answers1

2

I'm pretty sure Clang is right.

According to [temp.deduct.call]/4

In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference: [...]

A is the transformed argument type used in the call. The transformations referred to include certain conversions (e.g. array to pointer decay) that are not relevant here. Importantly, only the type A can be considered for the deduction (not the form of the actual argument), and the type A is A<0>. From the type A<0>, how can GCC deduce what the template parameter I (of type const int&) should be?

It can't be a reference to a, because the fact that the 0 came from a is not part of the type of the argument A<a>{}. I think GCC is materializing a temporary and taking I as a reference to that temporary. But [temp.arg.nontype]/3.1 bans this, so the result ought to be a deduction failure.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312