doug
doug

Reputation: 4299

Templated references to std::array not invoking SFINAE* in MSVC . Bug?

I ran across a problem upgrading templated array references to std::array where I had used this:

template<class T, int N>
void f(T(&a)[N]){/* do stuff */;}

This has worked in all compilers I have used so I just did this when changing to std::array

template<class T, int N>
void f(std::array<T,N>& a){/* do stuff */;}

And this worked fine on MSVC. But when I ran the code on other compilers it did not The following code works in MSVC but not other compilers. See https://godbolt.org/z/d9cqWMeaM which fails to match because N must be std::size_t.

*This question indicates that SFINAE should apply. However, as noted in the comments and in spite of the that answer, SFINAE, typically applies to rejection of malformed declarations. This is a deduction failure.

Is MSVC's acceptance of this code a compiler bug? And is the T(&a)[N] where int N was used legal even though all compilers I've ever used had no problem at all?

This was somewhat annoying because some of the prior code used the fact N was signed in various places.

Upvotes: 2

Views: 83

Answers (1)

rustyx
rustyx

Reputation: 85471

std::array size_type is specified as std::size_t.

GCC and Clang are right, template deduction should fail in this case, according to [temp.deduct.type]/18:

If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails.
. . .

[ Example:

template<int i> class A { /* ... */ };
template<short s> void f(A<s>);
void k1() {
  A<1> a;
  f(a);             // error: deduction fails for conversion from int to short
  f<1>(a);          // OK
}

Note: in C++11 this rule was a little more human-readable, see here.

So technically MSVC's acceptance of the code is a bug. I would report it to the vendor (Help -> Send Feedback -> Report a Problem).

Upvotes: 2

Related Questions