函数模板重载

函数模板的重载

#include <cstring>
#include <iostream>
#include <typeinfo>
using namespace std;
template<typename T>
T const& max (T const& x, T const& y) {
    cout << "<1" << typeid (x).name () << '>'
        << flush;
    return x < y ? y : x;
}
char const* const& max (char const* const& x,
    char const* const& y) {
    cout << "<2" << typeid (x).name () << '>'
        << flush;
    return strcmp (x, y) < 0 ? y : x;
}
/*
char const* max (char const* x, const char* y) {
    return strcmp (x, y) < 0 ? y : x;
}
*/
template<typename T>
T* const& max (T* const& x, T* const& y) {
    cout << "<3" << typeid (x).name () << '>'
        << flush;
    return *x < *y ? y : x;
}
template<typename T>
T const& max (T const& x, T const& y, T const& z) {
    cout << "<4" << typeid (x).name () << '>'
        << flush;
    return ::max (::max (x, y), z);
}
/*
char const* const& max (char const* const& x,
    char const* const& y) {
    cout << "<2" << typeid (x).name () << '>'
        << flush;
    return strcmp (x, y) < 0 ? y : x;
}
*/
int main (void) {
    cout << ::max (123, 456) << endl;
    cout << ::max (1.23, 4.56) << endl;
    cout << ::max<string> ("hello", "world")
        << endl;
    cout << ::max ("hello", "world") << endl;
    int x = 123, y = 456;
    cout << *::max (&x, &y) << endl;
    char const* a = "ABC";
    char const* b = "AB";
    char const* c = "A";
    // 编译器优先选择普通函数
    cout << ::max (a, b) << endl; // 2
    // 除非函数模板能够产生具有更好匹配性的函数
    int d = 100, e = 200;
    cout << ::max (d, e) << endl; // 1
    // 在参数传递过程中如果需要隐式类型转换,编译器
    // 只能选择普通函数
    cout << ::max (a, (char*)b) << endl; // 2
    // 通过模板参数表告知编译器使用函数模板
    // 针对指针的版本显然比任意类型版本更加具体
    cout << ::max<> (b, a) << endl; // 3
    // 显式指定的模板参数必须在所选择的重载版本中与
    // 调用参数的类型保持一致
    cout << ::max<char const*> (b, a) << endl; // 1
    cout << ::max (123, 789, 456) << endl;
    // 在函数模板的实例化函数中,编译器优先选择普通
    // 函数,但是该普通函数必须声明于模板之前
    cout << ::max (a, b, c) << endl;
    char const* const& r = max (a, b, c);
    cout << r << endl; // ABC
    char const* g = "123";
    char const* h = "12";
    char const* i = "1";
    max (g, h, i);
    cout << r << endl; // ABC
    return 0;
}

一次编译和二次编译:

  重载选择的时机问题:

  模板在第一次编译时,会生成模板函数的内部表示,二次编译实例化模板,此时生成具体指令,确定重载版本,参数类型T具体类型已经知道。

  但是可供选择的普通函数或者模板函数必须声明于该模板函数之前。因为,单向编译器在二次编译确定选择哪一个,但具体选择范围在一次编译时确定。在一次编译时,编译到该模板时只能看见其前面的重载版本。

猜你喜欢

转载自www.cnblogs.com/kuikuitage/p/9315749.html