C++ Templates:模板实参演绎

演绎的过程:
描述实参-参数对匹配情况:
匹配类型A(来自实参的类型),参数化类型P(来自参数的声明)
如果实参的是数组或函数类型,那么会发生decay转型,转化为对应的指针类型,同时还会忽略高层次的const和volatile限定符。
template <typename T> void f(T);    //P就是T
template <typename T> void g(T&);    //P仍然是T
double x[20];

int const seven = 7;

f(x);            //T是double*
g(x);            //T是double[20]
f(seven);        //T是int
g(seven);        //T是int const
f(7);            //T是int
g(7);            //错误,不能把传递给int&

演绎的上下文:
template <typename T1, typename T2, typename T3>
void f(T1 (T2::*) (T3*) );

class S {
public:
    void f(double*);
};

void g(int*** ppp) {
    f(&S::f);
}
演绎T1=void,T2=S,T3=double。
解释:
f的参数是一个函数,函数的返回值是T1,函数的依赖关系由T2::*体现,函数的参数是T3*。

例:
template <int N>
class X {
  public:
    typedef int I;
    void f(int) {
    }
};

template<int N>
void fppm(void (X<N>::*p)(typename X<N>::I));

int main()
{
    fppm(&X<33>::f);  // 正确,N被演绎成33
}
子构造X<N>::I是一个不可演绎的上下文,然而,具有成员指针类型的成员类型部分X<N>是一个可以演绎的上下文。

特殊的演绎情况:
1.取函数模板的地址
template <typename T>
void f(T, T);

void (*pf) (char, char) = &f;

2.与转型运算符模板一起出现
class S {
public:
    template<typename T, int N> operator T[N]&();
};

void f(int (&)[20]);

void g(S s) {
    f(s);    //能成功演绎
}

可接受的实参转型:
1.如果原来声明的参数是一个引用参数子,那么被替换的P类型可以比A类型多一个const或volatile限定符
2.如果A类型是指针类型或者成员指针类型,那么它可以进行限定符转型,转化为被替换的P类型
3.当演绎过程不涉及到转型运算符模板的时候,被替换的P类型可以是A类型的基类,或者当A是指针类型时,P可以是一个指针类型,它所指向的类型是A所指向的类型的基类。

类模板参数:
模板实参演绎只能应用于函数模板和成员函数模板,是不能应用于类模板的。对于类模板的构造函数,也不能根据实参来演绎类模板参数。

缺省调用实参:
对于缺省调用实参而言,即使不是依赖型的,也不能用于演绎模板实参:
template <typename T>
void f(T x = 42) { }

int main() {
    f<int> ();    //正确
    f();        //错误,不能根据缺省调用实参来演绎T
}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值