[C++] 模板编程-11 模板类型的推导

一 推导

  • 这里的推导指的是,调用模板函数时由编译器根据上下文来推断所调用的模板函数模板参数。

二 示例

指针类型推导

  • 由于编译器可以自动推导出这个类型也就是三层指针,所以我们没有使用<>传入这个模板函数的类型。
template <typename T>
void baseFunction(T*)
{
    qDebug()<<typeid(T).name();
}
    int ****pointer = nullptr;
    baseFunction(pointer);

数字大小自动推导

  • 这里值得注意的是 T(&p): &p是一个引用,引用的是T的类型
  • 这里T自动被推导为int,而N被推导为10
  • 如果需要手动指出则需要: baseFunction<int,10>(array);
template <typename T,int N>
void baseFunction( T(&p)[N] )
{
    qDebug()<<N<<","<<typeid(T).name()<<","<<p[2];
}
int array[10] = {1,2,3,4,5};
char str[100] = "hello world";
baseFunction(array); 

类的函数指针推导

  • 首先我们定义一个模板
  • 因为T2::*t2 是这样调用的,很明显第一个参数其实是一个类的成员函数指针。
template <typename T1,typename T2,typename T3>
void func(T1(T2::*t2)(T3),T3 t3) // T2一定是个类/结构体类型 并且是一个函数 返回值为T1 参数为T3
{   
 T2 instance;   
 (instance.*t2)(t3);   
 qDebug()<<typeid(T1).name()<<" "<<typeid (T2).name()<<"  "<< typeid (T3).name();
}
  • 然后定义一个类,以及一个类的成员函数(方法):
class testFunc
{
public:  
  int test_Func(int bbb) 
{   
     qDebug()<<bbb; 
}
};
  • 自动推导: 
  • 如果上面的类的成员函数我们定义为double,就不能推到成功了,因为在调用时,编译器不能推断出,它是double还是float
func(&testFunc::test_Func,100);
  • 同样的我们推导一个非类型参数的函数模板
template <int N>
class X
{
public:
    typedef  int iInt;
    void f(int n)
    {
        qDebug()<<10 + N + n;
    }
};

template<int N>
void function(void(X<N>::*p)(typename X<N>::iInt))
{
    X<N> x;
    (x.*p)(N);
    qDebug()<<N;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    function(&X<5>::f);

    return a.exec();
}

函数指针类型推导

template <typename T>
void Func(T t1)
{
    qDebug()<<typeid (T).name() << "," << t1;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    void(*function)(char) = &Func;

    function('A');

    return a.exec();
}

类继承的自动推导

  • 当调用 Func(m1); 时,Func 被实例化为 Func<M<int>>,并输出 int 的类型名称。
  • 当调用 Func(n1); 时,Func 被实例化为 Func<N<double>>,但由于 N<double>M<double> 的派生类,所以它能被隐式转换为 M<double>,进而输出 double 的类型名称。
template <typename T>
class M
{

};

template<typename T>
class N : public M<T>
{

};

template <typename T>
void Func(M<T>)
{
    qDebug()<<typeid (T).name();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    M<int> m1;
    N<double> n1;
    Func(m1);
    Func(n1);
    return a.exec();
}

右值引用

  • 通过这种右值引用T&&,可以智能的处理左值和右值
  • 比如如果传进去是左值,int template = 100; 传入template,则被绑定为T &t
  • 如果传入是一个 100,则被绑定为 T &&t
template <typename T>
void Func(T && t)
{
    qDebug()<<typeid (T).name();
}

    int templateA = 100;
    Func(templateA);
    Func(100);
    Func('1');
    Func("100");

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值