• 28、C++ Primer 4th 笔记,模板与泛型编程(3)


    1、用const char*实参调用如下模板,则比较的是指针值,而不是指向的字符串。此时需要模板特化。

    示例

    template <typename T>
    int compare(const T &v1, const T &v2)
    {
    	if (v1 < v2) return -1;
    	if (v2 < v1) return 1;
    	return 0;
    }
    

    2、函数模板的特化:一个或多个模板形参的实际类型或实际值是指定的。

    • 关键字 template 后面接一对空的尖括号(<>);

    • 再接模板名和一对尖括号,尖括号中指定这个特化定义的模板形参;

    • 函数形参表;

    • 函数体。

    示例代码

    // special version of compare to handle C-style character strings
    template <>
    int compare<const char*>(const char* const &v1,
    						 const char* const &v2)
    {
    	return strcmp(v1, v2);
    }
    

    特化的声明必须与对应的模板相匹配。

    1)、与任意函数一样,函数模板特化可以声明而无须定义。

    示例

    // declaration of function template explicit specialization
    template<>
    int compare<const char*>(const char* const&,
    						 const char* const&);
    

    2)、省略template<>则结果是声明该函数的重载非模板版本。

    示例

    // generic template definition
    template <class T>
    int compare(const T& t1, const T& t2) { /* ... */ }
    // OK: ordinary function declaration
    int compare(const char* const&, const char* const&);
    

    当定义非模板函数的时候,对实参应用常规转换,当特化模板的时候,对实参类型不应用转换。

    3)、如果程序由多个文件构成,模板特化的声明必须在使用该特化的每个文件中出现。

    3、类模板的特化

    示例

    /* definition of specialization for const char*
    * this class forwards its work to Queue<string>;
    * the push function translates the const char* parameter to a string
    * the front functions return a string rather than a const char*
    */
    template<> 
    class Queue<const char*> 
    {
    public:
    	// no copy control: Synthesized versions work for this class
    	// similarly, no need for explicit default constructor either
    	void push(const char*);
    	void pop() {real_queue.pop();}
    	bool empty() const {return real_queue.empty();}
    	// Note: return type does not match template parameter type
    	std::string front() {return real_queue.front();}
    	const std::string &front() const
    	{return real_queue.front();}
    private:
    	Queue<std::string> real_queue; // forward calls to real_queue
    };
    
    void Queue<const char*>::push(const char* val)
    {
    	return real_queue.push(val);
    }
    

        在类特化外部定义成员时,成员之前不能加 template<> 标记。

    1)除了特化整个类模板之外,还可以只特化成员,但是成员特化的声明与任何其他函数模板特化一样,必须以空的模板形参表开头。

    示例

    template<>
    void Queue<const char*>::push(const char* const&);
    

    2)类模板的部分特化

    类模板的部分特化本身也是模板。编译器将为实例化选择最特化的模板定义。

    示例

    template <class T1, class T2>
    class some_template {
    // ...
    };
    // partial specialization: fixes T2 as int and allows T1 to vary
    template <class T1>
    class some_template<T1, int> {
    // ...
    };
    
    some_template<int, string> foo; // uses template
    some_template<string, int> bar; // uses partial specialization
    

    4、重载与函数模板

    函数模板可以重载:可以定义有相同名字但形参数目或类型不同的多个函数模板,也可以定义与函数模板有相同名字的普通非模板函数。

    普通函数优先于模板版本。当匹配同样好时,非模板版本优先。

    5、函数模板是建立算法库的基础,类模板是建立标准库容器和迭代器的基础。

    6、几个关键概念:

    1)泛型句柄类:保存和管理指向其他类的指针的类。泛型句柄接受单个类型形参,并且分配和管理指向该类型对象的指针。句柄类定义了必要的复制控制成员,*,->操作符。不需要了解它管理的类型。

  • 相关阅读:
    css技巧和经验列表
    CSS3嵌入字体@font-face调用字体
    新闻列表单行滚动(多行显示)简洁向上滚动js效果
    打破构图的平衡!增强设计感染力
    何以双十(补昨天)
    MySQL5.7 基于二进制包的安装
    Nginx Log日志统计分析常用命令
    MySQL错误代码大全
    MVC4中的Display Mode简介
    ReadOnly关键字修饰的变量可以修改,只是不能重新分配
  • 原文地址:https://www.cnblogs.com/mydomain/p/2012441.html
Copyright © 2020-2023  润新知