The following code compiles and works fine with gcc (9), clang (11) and msvc (16.28):
template <class A>
struct X {
A a;
constexpr X(A a) : a{a} { }
};
template <class A>
constexpr auto fn(X<A> const& x) {
return X<A>(x.a - 1);
}
template <class Xs, class A>
constexpr auto fn(X<A> const& x) {
return Xs(x.a - 1);
}
constexpr X<int> x1{3};
constexpr auto x2 = fn(x1);
constexpr auto x3 = fn<X<double>>(x1);
There are two fn functions with identical declarations except for the extra Xs parameter in the second one.
I'd like to be sure that this is standard-accepted and not something that these compilers provide as extra? Since all 3 do, I'd guess this would be standard, but you never know.
I'd also like to know if my assumptions as to why this work/would be standard are correct:
- in the call
fn(x1),Xscannot be deduced so the second overload offnis discarded gently (SFINAE?)? - in the call
fn<Xs>(x1), the first overload would then befn(X<X<int>>)which does not match the argumentx1, thus the first overload is also discarded?