★06.关于函数模板

2017-06-30  本文已影响0人  iDragonfly

定义:

template <typename T>
void fun(T t) {
}

特化

代码

template<typename T>
void fun1(T t) {
    std::cout << "fun1(T t)" << std::endl;
}

// 通过自动推断来确定模板参数T的函数模板特化
template<>
void fun1(int t) {
    std::cout << "fun1(int t)" << std::endl;
}

template<typename T>
void fun2() {
    T t;
    std::cout << "fun2<T>()" << std::endl;
}

// 通过显式说明模板参数T为int的函数模板特化
template<>
void fun2<int>() {
    int t;
    std::cout << "fun2<int>()" << std::endl;
}

int main() {
    fun1(0.0);
    fun1(0);
    fun2<double>();
    fun2<int>();
    return system("pause");
}

输出

fun1(T t)
fun1(int t)
fun2<T>()
fun2<int>()

默认模板实参【C++11】

template<typename T, typename F = int>
void fun() {
}

显式指定模板实参

template <typename T>
void fun(T t) {
}

int main() {
    fun<int>(0.0);
    return system("pause");
}

显式实例化

// 声明函数模板实例化的作用是避免编译期多次重复实例化,可以达到加块编译速度的效果
// 下述两行代码不能出现在同一文件
template void fun(int t);          // 定义,代表此处将函数模板fun()实例化为fun<int>
extern template void fun(int t);   // 声明,代表承诺在别的文件有个fun<int>实例化

int main() {
    fun<int>(1);                   // 此处实际上没有实例化的过程,会复用已经声明的实例化
    return system("pause");
}

尾置返回类型的应用

// 此处不得不使用尾置返回类型,因为我们不知道beg的解引用是什么类型,而且beg知道参数列表才出现
template <typename T>
auto fun1(T beg, T end) -> decltype(*beg) {
    return * beg;
}

// decltype会把(*beg)推断为引用类型,想要移除引用可以使用remove_reference<decltype(*beg)>::type
template <typename T>
auto fun2(T beg, T end) -> typename remove_reference<declval(*beg)>::type {
    return * beg;
}

转发型引用

如果模板参数是T &&的形式,则可以给它传递任何类型的实参,详情请查阅转发型引用。

重载匹配问题

template<typename T1>
void fun(T1 t1, T1 t2) {
    std::cout << " 1" << std::endl;
}


template<typename T1, typename T2>
void fun(T1 t1, T2 t2) {
    std::cout << "2" << std::endl;
}


void fun(int t1, double t2) {
    std::cout << "3" << std::endl;
}

// 注意:特化本质上是实例化一个模板,而非重载它,不会影响函数匹配
template<>
void fun(int t1, int t2) {
    std::cout << "4" << std::endl;
}

// 注意:特化本质上是实例化一个模板,而非重载它,不会影响函数匹配
template<>
void fun(int t1, double t2) {
    std::cout << "5" << std::endl;
}


int main() {
    // 不用经过类型转换的函数匹配都叫精确匹配,有多个精确匹配版时,根据如下规则选择:
    fun(1, 1.0);            // 规则一:当只有一个非模板函数精确匹配时,优先选择此函数(1、2、3中选择3)
    fun(1.0, 1.0);          // 规则二:规则一不满足时,优先选择更特例化的函数模板版本(1、2、3中选择1)
    fun(1, 1);              // 规则二:规则一不满足时,优先选择更特例化的函数模板版本(1、2、3中选择1的特化版本4)
                            // 规则三:上述规则都失效时,调用有二义性。
    return system("pause");
}
上一篇 下一篇

猜你喜欢

热点阅读