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:
fn(x1)
, Xs
cannot be deduced so the second overload of fn
is discarded gently (SFINAE?)?fn<Xs>(x1)
, the first overload would then be fn(X<X<int>>)
which does not match the argument x1
, thus the first overload is also discarded?A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.
You may overload a function template either by a non-template function or by another function template. If you call the name of an overloaded function template, the compiler will try to deduce its template arguments and check its explicitly declared template arguments.
Overloading function templates (C++ only) You may overload a function template either by a non-template function or by another function template. If you call the name of an overloaded function template, the compiler will try to deduce its template arguments and check its explicitly declared template arguments.
The compiler proceeds with overload resolution, choosing the most appropriate function from the set of candidate functions. Non-template functions take precedence over template functions. The following example describes this:
Function overloading in python can be of two types one is overloading built-in functions and overloading the custom or user-defined functions in python. We will have a look into both of them in the below sections. In general, not every programming language supports function overloading but in this case, python supports functional overloading.
There are two
fn
functions with identical declarations except for the extraXs
parameter in the second one.
That's fine, you can overload function templates using different arguments or different template arguments.
- in the call
fn(x1)
,Xs
cannot be deduced so the second overload offn
is discarded gently (SFINAE?)?
Yes, except it's not SFINAE, but overload resolution. The S in SFINAE stands for substitution. When a template argument can't be deduced, no substitution takes place.
It's described in [temp.over]/1:
... For each function template, if the argument deduction and checking succeeds, the template-arguments (deduced and/or explicit) are used to synthesize the declaration of a single function template specialization which is added to the candidate functions set to be used in overload resolution.
With regard to the second bullet (fn<X<double>>(x1)
), both templates can synthesize a valid declaration, but X<int>
isn't convertible to X<X<double>>
, so the second overload is selected as the only viable one.
Note: when multiple template overloads are viable, partial ordering is performed to determine the most specialized template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With