Home > Back-end >  Template use without angle brackets - Overloading?
Template use without angle brackets - Overloading?

Time:09-17

I'm a little confused about the idea of using template with <> brackets and without them. When I compiled the code I got the output I wasn't expecting, and didn't figure out why.

For example, let's say I have 2 functions and a template with the same prototype:

using namespace std;

template<typename T> void copy(T a, T b)
{
    cout << "template copy" << endl;
}
void copy(int a, int b)
{
    cout << "int copy" << endl;
}
void copy(string a, string b)
{
    cout << "string copy" << endl;
}

And after compiling the main function:

int main()
{
    copy<int>(1, 2);
    copy<string>("ha", "ha");
    copy("ab", "bc");
    copy(1, 2);
    
    return 0;
}

the output looked like this:

template copy
template copy
template copy
int copy

for the record all the code is written on the same CPP file.

CodePudding user response:

You have to remember that literal strings are really (constant) arrays of characters, which decays to (constant) pointers to char, i.e. const char*.

Since your function taking std::string arguments is not a direct match, and the compiler will not do a conversion, the template overload will be used (as copy<const char*>).

CodePudding user response:

In these calls

copy<int>(1, 2);
copy<string>("ha", "ha");

you explicitly specified the template argument. So the compiler will consider only template functions.

In this call

copy("ab", "bc");

you did not specify the template argument. So the compiler will consider all overloaded functions with the name copy and select the most viable function.

The type of arguments that represent string literals is const char [3].

Due to the standard conversion sequence the arguments are explicitly converted to pointers to first characters of the string literals of the type const char *.

So the compiler can deduce the type of the template argument as the type const char *.

To call the non-template function

void copy(string a, string b)
{
    cout << "string copy" << endl;
}

the compiler needs to use one more conversion (user-defined conversion) to convert the pointers to objects of the type std::string.

So as the template function requires less conversions then it is considered by the compiler as more suitable. And as a result you get the output

template copy

Here is a demonstrative program.

#include <iostream>
#include <iomanip>
#include <type_traits>

template <typename T>
void f( T , T )
{
    std::cout << std::boolalpha << std::is_same<T, const char *>::value << '\n';
}

int main() 
{
    f( "ab", "bc" );
    
    return 0;
}

The program output is

true
  • Related