Reputation: 6982
I am still trying to figure out templates. I have read about the specialization rules and don't understand what is happening here.
I have defined the following in templates.h:
#include <iostream>
template <typename foo>
void f(foo p)
{
std::cout << "one" << std::endl;
}
template <typename bar>
void f(int p)
{
std::cout << "two" << std::endl;
}
Now if I include this and call it in my main like this
f(1);
f("x");
I get
one
one
Now the questions is, why is the first more specific than the second for ints? I feel like it should at least be ambiguous and not work at all.
Upvotes: 3
Views: 80
Reputation: 227418
The second overload one has no template dependency on function arguments, so you would have to call it like this:
f<std::string>(1);
f<double>(42);
f<SomeType>(1);
Whether it makes sense to have the second version is a different matter. You could imagine having a template parameter that does have some effect on the internal logic of the function:
template <typename SomeType>
int foo(int seed) {
// instantiate a SomeType and use it to calculate return value
};
int i = foo<Type1>(42);
int j = foo<Type2>(42);
On the other hand, your SomeType
could be a function parameter:
template <typename SomeType>
int foo(int seed, const SomeType& s) {
// use s to calculate return value
};
Type1 t1;
Type2 t2;
int i = foo(42, t1);
int j = foo(42, t2);
Upvotes: 4
Reputation: 2594
The one, which prints "two" is not recognized as explicit specialization. Try thisL
template <>
void f(int p)
{
std::cout << "two" << std::endl;
}
Upvotes: 0
Reputation: 477110
First off, you don't have specializations, but two separate, unrelated overloads.
Secondly, the second overload is trivially non-viable, since you call the function without template arguments, and thus there is no way to deduce the template parameter bar
. So only the first overload is viable, and gets used.
An actual specialization would look like this:
template <>
void f<int>(int p) { /* ... */ }
Better yet, stick with overloads (it's generally better to overload functions than to provide template specializations), but make the second one a non-template:
void f(int p) { /* ... */ }
Upvotes: 5
Reputation: 13486
In the second one bar
cannot be deduced from function arguments, and must be given explicitly:
f<whatever>(1);
Upvotes: 1