没有尖括号的模板使用 - 重载?

Template use without angle brackets - Overloading?

我对使用带 <> 括号和不带括号的 template 的想法有点困惑。当我编译代码时,我得到了我没有预料到的输出,并且没有弄清楚为什么。

例如,假设我有 2 个函数和一个具有相同原型的 template

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;
}

编译主要功能后:

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

输出如下所示:

template copy
template copy
template copy
int copy

郑重声明,所有代码都写在同一个 CPP 文件中。

您必须记住,文字字符串实际上是(常量)字符数组,它会衰减为指向 char 的(常量)指针,即 const char*.

由于采用 std::string 参数的函数不是直接匹配,并且编译器不会进行转换,因此将使用模板重载(如 copy<const char*>)。

在这些调用中

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

您明确指定了模板参数。所以编译器只会考虑模板函数。

在本次通话中

copy("ab", "bc");

您没有指定模板参数。所以编译器会认为所有名称为copy和select的重载函数是最可行的函数。

表示字符串文字的参数类型是const char [3]

由于标准转换顺序,参数被显式转换为指向 const char *.

类型字符串文字的第一个字符的指针

因此编译器可以将模板参数的类型推断为类型const char *

调用非模板函数

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

编译器需要再使用一次转换(用户定义的转换)将指针转换为 std::string.

类型的对象

因此,由于模板函数需要较少的转换,因此编译器认为它更合适。结果你得到了输出

template copy

这是一个演示程序。

#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;
}

程序输出为

true