guevara / read-it-later

read it later
231 stars 0 forks source link

为什么函数模板没有偏特化_函数模版没有偏特化-CSDN博客 #11858

Open guevara opened 3 weeks ago

guevara commented 3 weeks ago

为什么函数模板没有偏特化?_函数模版没有偏特化-CSDN博客

https://ift.tt/kgC6F3Z



背景

先来看一个毁三观的demo


template <typename A, typename B>
void f(A a, B b) {
    std::cout << "Normal version." << std::endl;
}
template<>
void f<int, int>(int a, int b) {
    std::cout << "Full Special version." << std::endl;
}

template <typename A>
void f(A a, int b) {
    std::cout << "Partial version." << std::endl;
}

int main()
{
    int a = 10;
    double b = 12;  
    f(a, b);
    f(a, a);
}

Normal version.
Partial version.

分析

上面的代码可以看到,函数在调用时候顺序是:

  1. 有匹配的no-template函数就优先调用,没有再进行下一步
  2. 先找合适的模板,在本demo中,合适的模板就是second template
  3. 找到模板后,在模板的实例化函数中找一个最合适的
  4. 如果该模板没有最合适的函数,那么就由编译器根据该模板自己实例化一个
    在这里插入图片描述

结论

从上面的代码可以看到,函数并不需要偏特化,只要重载一个模板就可以实现偏特化的效果。切记,C++函数没有偏特化,下面的写法会报错,简单说不允许特化的时候template后面<>还有值存在
在这里插入图片描述
在这里插入图片描述

思考

目前经常推荐enable_if, 但当我实际使用的时候,会发现编译器提醒模板重定义, 所以模板也是存在重定义问题,这里重定义的原因是,两个模板的签名都是:<typename T1, typename T2, typename dummy> + void show(T1, T2), 所以在下面的使用enable_if方法时,只能出现一个enable_if, 这个函数是为了限制某个参数必须满足某个条件。

template<typename T1, typename T2, typename dummy = enable_if_t<is_same<T2, int>::value>>
void show(T1 a, T2 b)
{
        cout<<" partial T2 = int" << endl; 
}

template<typename T1, typename T2, typename dummy = enable_if_t<is_same<T2, float>::value>>
void show(T1 a, T2 b)
{
        cout<<" partial T2 = float" << endl; 
}

如果想实现上面的效果,可以下面操作, 我们知道,模板参数也是可以穿入指针类型的,这里enable_if一旦成立会生成void*。这里为什么没有模板重定义问题呢?我们知道typename不管传入类型是啥,比如int, float, char 反正模板签名里类型就是typename, 但是指针就不一样了,int*, char* ,double* 在模板签名里看就是不同的类型了,所以不会出现重复定义的问题。这个要好好想明白,不然就弄不懂类偏特化时候enable_if的使用方法。

template<typename T1, typename T2, enable_if_t<is_same<T2, int>::value>*  dummpy = nullptr >
void show(T1 a, T2 b)
{
        cout<<" partial T2 = int" << endl; 
}

template<typename T1, typename T2, enable_if_t<is_same<T2, float>::value>*  dummpy = nullptr >>
void show(T1 a, T2 b)
{
        cout<<" partial T2 = float" << endl; 
}

以上的实验放在类模板上也是成立的

总结

函数只有全特化,也就是说一个函数模板只能全特化,但是可以进行模板的重载,重载的时候注意typename和指针的效果

参考

https://ift.tt/oxb5nMI







via CSDN博客-专业IT技术发表平台

November 1, 2024 at 12:29AM