C++模板编程(10)---更深入的基础技术:模板参数(Template Parameter)

Template parameters有三种类型:

  • 类型参数Type parameters
  • 非类型参数 Non-type Parameters
  • 双重模板参数 Template Template Parameters

所谓模板参数template parameters是在模板声明语句的参数化子句(parameterized clause)中声明的变量。Template parameters不一定要署名:

template <typename , int >  // 这里,两个模板参数都没有名称

class X;

但是当template程序中需要用到某个template parameter时,后者就必须署名。另外,后面声明的template parameters可以用到先声明的template parameters的名称,反之不然:

template <typename T,                   //第一个参数T,被用于第二和第三参数的声明中

                T* Root,

                template<T*> class Buf > //Buf, 就是template template parameter

class Struture;

1. 类型参数Type Parameters

Type parameters可以采用关键词typename 或关键词class导入,两者等价。其声明形式是:关键词typename 或class后面跟一个简单标识符,该符号后面可跟一个逗号以便区隔下一个参数,也可以使用闭锁角括号结束参数子句,或跟一个等号=标识出预设模板自变量default template argument。

在template 声明语句中type parameter的作用非常类似typedef的名称。例如不能使用如class T这样的完整名称,即使T确实表示一个class type:

template <typename Allocator>

class List {

        class Allocator* allocator;//Error

        friend class Allocator; //Error     

        ...    

};

2. 非类型参数NonType Parameters

Nontype template parameter是指那些可在编译期或链接期确定其值的常数。此种参数的类型必须是以下三者之一:

  • 整数integral或列举enumeration类型
  • pointer类型:包括指向常规objects、指向functions和指向members
  • referenc类型:包括指向objects或指向functions。

令人惊讶的是,nontype parameter的声明在某种情况下也以关键词typename为前缀词

template <typename T,                                             //type parameter

                typename T::Allocator* Allocator>            //nontype parameter

class List;

Nontype parameters 也可以是functions类型或array类型,但它们都会退化为对应的pointer类型:

template <int buf[5]> class Lexer;

template <int* buf> class Lexer;

Nontype template parameters的声明类似变量声明,但不能加上static、mutable之类的修饰。你可以加上const或volatile,但如果修饰词出现在参数类型的最外层,编译器会忽略它们:

template  <int const length> class Buffer;

template <int length> class Buffer; //与上一行等价

最后一点,nontype parameters总是右值rvalues:它们不能被取值,也不能被赋值,

3. 双重模板参数Template Template Parameter 

template template parameters是一种class template占位符,其声明方式和class template类似,只是不能使用关键词struct和union:

template  <template <typename X> class C>   //OK

void f(C<int>* p);

template <template<typename X> struct C> //Error

void f(C<int>* p);

template <template<typename X> union C> //Error

void f(C<int>* p);

在它们的作用域内,你可以像使用class template那样地使用template template parameters。

1)template template parameters的参数也可以default template arguments

如果客户端没有为响应的参数指定自变量,编译器就会使用这些预设自变量:

template <template <typename T,

                                typename A = MyAllocator> class Container>

class Adaptation {

        Container<int> storage; //等价于 Container<int, MyAllocator>

        ...

};

2)template template parameters中,template parameter的名称只能被用于template template parameter 的其他参数声明中。

template <template<typename T, T*> class Buf>

class Lexer {

        static char storage[5];

        Buf<char, &Lexer<Buf>::storage[0]> buf;

        ...

};

template <template<typename T> class List>

class Node {

        static T* storage;

        ...

};

3)通常template template parameter中的template parameters名称并不会在其他地方用到,因此,未被用到的template parameter可以不署名。

例如,上面的Adaption template可被声明为:

template <template> <typename,

                                typename = MyAllocator> class Container>

class Adaptation

{

        Container<int> storage;  //等价于Container<int, MyAllocator>

        ...

}

4. 预设的模板引数Default Template Arguments

目前,只有class template的声明语句可以存在default template argument。无论何种template parameter都可以有预设的自变量,当然它必须匹配对应参数。很明显,预设自变量不能相依于其自身参数,但可以相依于之前声明的参数:

template <typename  T, typename Allocator = allocator<T> >

class List;

和函数的预设自变量一样,某个参数(不论是调用参数还是模板参数)带有预设自变量的条件是:其后续所有参数也都有预设自变量。

后续参数的预设自变量通常写在同一个template声明语句中,但也可以写在该template更早的某个声明语句中。例如,

template <typename T1, typename T2, typename T3,

                typename T4= char , typename T5 = char>

class Quintuple;   //OK

template <typename T1, typename T2, typename T3 = char,

                typename T4, typename T5>

class Quintuple; //OK: T4, T5先前已经有默认值

template <typename T1=char, typename T2, typename T3,

                typename T4, typename T5>

class Quintuple;  //错误:T1不能有默认值,因为T2没有默认值

此外,我们也不能重复指定default template arguments:

template <typename T = void>

class Value;

template <typename T= void > //Error:预设自变量重复

class Value;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值