• 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;

  • 相关阅读:
    Chrome浏览器不好用?因为你没安装扩展插件
    java设计模式
    决策树算法
    【SpringBoot源码】源码分析
    java 字符串只保留数字、字母、中文
    赚够钱回老家吗
    java计算机毕业设计高校排课管理系统MyBatis+系统+LW文档+源码+调试部署
    javascript注册表单与验证,然后弹出错误信息,3秒后自动消失
    《Jetpack Compose从入门到实战》第三章 定制 UI 视图
    HarmonyOS应用开发-ArkTS基础知识
  • 原文地址:https://blog.csdn.net/zkmrobot/article/details/125491187