User StoryTeller gave the best straight up answer coming from the standard. I would like to elaborate on this by giving a break down example of how compilers treat this:
Let's look at your current code:
#include <iostream>
using namespace std;
template<typename T>
T add(double a, double b) {
return static_cast<T>(a + b);
}
int main() {
cout << add<int>(1.1, 1) << endl;
cout << add<double>(1.1, 1) << endl;
return 0;
}
Let's see how the compiler will treat this. Before we do that, remember this: templates have to be known at compile time and similar to how C++ replaces text with macros and defines it does something of that nature for templates as well when they become instantiated.
Your function template has this signature: this will generate which ever function it needs to satisfy T.
template<typename T>
T add(double a, double b) {
return static_cast<T>(a + b);
}
However in this case T is not a part of the signature. The function's signature looks like this:
::add<T>(double, double)
And since the templates argument refers to its return type as opposed to one of its parameters it has no effect here.
Let's look at this as if we weren't using templates. For demonstration purposes only: ignore the fact that the following will create ambiguous functions:
int add( double, double );
float add( double, double );
double add( double, double );
Now let's apply the function calls in your main without the template version:
#include <iostream>
int main() {
std::cout << add( 1.1, 1 ) << '\n'; // <int> - reminder of original
std::cout << add( 1.1, 1 ) << '\n'; // <double> - ""
return 0;
}
Now looking at the code above, you have the same exact function call. So which overload does the add in this case call? It's quite simple; without using a template and ignoring the ambiguity, the above function would call double add( double, double ).
Since the above would generate a compiler error due to being ambiguous, let's go back and apply the template to investigate why this ambiguity doesn't happen with the template version.
-Original Code-
#include <iostream>
template<typename T>
T add( double a, double b ) {
return static_cast<T>( a + b );
}
int main() {
std::cout << add<int>(1.1, 1) << '\n';
std::cout << add<double>(1.1,1) << '\n';
return 0;
}
Let's see how the compiler treats this in a step by step fashion:
-Step 1: - Name Resolution, acquiring the function signature.
int main() {
std::cout << ::add<int>( 1.1, 1 ) << '\n';
std::cout << ::add<double>( 1.1, 1 ) << '\n';
return 0;
}
-Step 2: - Calling the function, and creating the function's call stack
int main() {
std::cout <<
::add<int>( 1.1, 1 ) {
return static_cast<int>( 1.1 + 1 );
}
<< '\n';
std::cout <<
::add<double>( 1.1, 1 ) {
return static_cast<double>( 1.1 + 1 );
}
<< '\n';
return 0;
}
-Step 3: - Performing all of the instructions within the function
int main() {
std::cout <<
/*::add<int>( 1.1, 1 ) {
return static_cast<int>( 1.1 + 1 );
}*/
return static_cast<int>( 2.1 );
<< '\n';
std::cout <<
/*::add<double>( 1.1, 1 ) {
return static_cast<double>( 1.1 + 1 );
}*/
return static_cast<double>( 2.1 );
<< '\n';
return 0;
}
-Step 4: - Returning the result back from the function and cleaning up the function call stack
int main() {
std::cout <<
return 2;
<< '\n';
std::cout <<
return 2.1;
<< '\n';
return 0;
}
-Step 5: - Main function is passing the returned results into the stream operators to the standard screen output.
int main() {
std::cout << 2 << '\n';
std::cout << 2.1 << '\n';
return 0;
}
And this matches your output exactly!
-Output-
2
2.1
I hope this break down helps you to understand templates better and to see why there is no ambiguity here as if you didn't use them. The bottom line here is that there is no ambiguity due to the fact that you explicitly instantiated the function templates.
Now try to run your program again but this time don't specify a type and let the compiler implicitly instantiate the function template. I believe you would get a compiler error!