Reputation: 55564
Consider the following example (godbolt):
template <typename T>
struct S {
S(int) {}
};
template <typename T>
void f(S<T>, T) {}
int main() {
f(1, 2);
}
Compiling it gives the following error:
<source>: In function 'int main()':
10 : <source>:10:11: error: no matching function for call to 'f(int, int)'
f(1, 2);
^
7 : <source>:7:6: note: candidate: template<class T> void f(S<T>, T)
void f(S<T>, T) {}
^
7 : <source>:7:6: note: template argument deduction/substitution failed:
10 : <source>:10:11: note: mismatched types 'S<T>' and 'int'
f(1, 2);
^
Making S
a non-template makes the example compile.
Why doesn't this code compile despite an implicit conversion from int
to S<T>
?
Upvotes: 3
Views: 224
Reputation: 275405
template functions are not functions. They are templates for writing functions.
template <typename T>
void f(S<T>, T) {}
this is a template for writing a function given a type T
.
Now, C++ will in some situations attempt to deduce T
for you. What it does is pattern match on every argument (at once).
If any argument fails to find a match, or the deduced types are inconsistent or incomplete, the deduction fails. No conversion or partial match is attempted. If matches are found, they are added as candidates to the overloads in consideration (with some rules here), then overload resolution kicks in.
At overload resolution time conversion is considered. At template type deduction it is not other than conversion to base.
In your case, S<T>
cannot deduce the type T
from 1
. So deduction simply fails. We never reach overload resolution where conversions are considered.
As it happens you can block an argument from being considered during deduction:
template<class T>struct tag_t{using type=T;}:
template<class T>using block_deduction=typename tag_t<T>::type;
template <typename T>
void f(block_deduction<S<T>>, T) {}
and now your main compiles.
Upvotes: 4