With the following code g++ fails:
template <typename X = int, typename T, typename ...R>
inline void func(const T&, R...) {}
template <typename T>
struct S {};
template <typename X = int, typename T, typename ...R>
inline void func(const S<T>&, R...) {}
int main() {
func(42);
func(S<int>()); // OK
func(S<int>(), 1); // NOK
func<int>(S<int>(), 1); // NOK
}
with:
<source>: In function 'int main()':
<source>:13:21: error: call of overloaded 'func(S<int>, int)' is ambiguous
func(S<int>(), 1); // NOK
^
<source>:13:21: note: candidates are:
<source>:2:17: note: void func(const T&, R ...) [with X = int; T = S<int>; R = {int}]
inline void func(const T&, R...) {}
^
<source>:8:17: note: void func(const S<T>&, R ...) [with X = int; T = int; R = {int}]
inline void func(const S<T>&, R...) {}
^
<source>:14:26: error: call of overloaded 'func(S<int>, int)' is ambiguous
func<int>(S<int>(), 1); // NOK
^
...
Reproducible with gcc v4.8.1 and v9.1. Compiles with clang (v3.0.0 and v8.0.0), icc (v13.0.1 and v19.0.1), msvc (v19.14 and v19.20).
Is the code valid or is this a bug in gcc?
EDIT: Thanks everyone, your feedback was helpful for me. FYI, bug 90642 has been filed; looking forward for a definite answer.
You may overload a function template either by a non-template function or by another function template. The function call f(1, 2) could match the argument types of both the template function and the non-template function.
The name of the function templates are the same but called with different arguments is known as function template overloading. If the function template is with the ordinary template, the name of the function remains the same but the number of parameters differs.
overloading is used when we have various functions , doing SIMILAR operations . template is used when we have various functions , doing IDENTICAL operations .
The template function works for int and char, but not float and string.
Interesting question. I think what you run into here is overload resolution, more specifically partial ordering rules for template specialization
I quote:
Informally "A is more specialized than B" means "A accepts fewer types than B".
I think the clang is correct to compile that and the resulution should take the second candiate
template <typename X = int, typename T, typename ...R>
inline void func(const S<T>& t, R... p) {}
Because in case the first argument is not of type S<T>
, it is no longer viable and thus more specialized.
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