《深入理解C++11》笔记--模板

上一篇:《深入理解C++11》笔记–扩展
本篇介绍第二章最后一部分内容,模板相关的扩展。

  • 模板函数的默认模板参数
  • 外部模板
  • 局部和匿名实参作为模板参数

模板函数的默认模板参数
大家都了解函数可以拥有默认形参,并且模板类可以有默认的模板参数,现在C++11中模板函数也可以有默认的模板参数了。例如:

template<typename T = int>    // C++98、C++11都能编译通过
class Testclass{
};

template<typename T = int>    // C++11编译通过
void test_fun(){}

模板函数的默认参数和模板类的默认参数有一点不同,模板类的默认参数必须从右到左,但是模板函数不比如此。

template<typename T1 = char, typename T2>  // 不能编译通过
class Testclass{
};

template<typename T1 = char, typename T2>  // 可以编译通过
void test_fun()
{
}

外部模板
外部指的就是extern修饰符,原来就一直有外部变量的概念。外部变量是为了防止同名的变量分别定义在不同的文件中时,在两份文件的数据区中产生两个相同名字的变量,其他文件同事调用这两个文件时,链接的时候会产生误解,无法成功链接。而在其中一个文件的声明时使用了extern修饰符,就会认为这个变量是一个外部的变量,不会再去生成数据区中的数据。
外部模板也是为了避免类似的问题,例如下面这段代码,在两个文件中分别使用了同一个模板函数的同一个类型,这样在编译的时候会分别生成相同两份代码,链接过程中链接器会自动删除多余的重复代码,这样就增加了编译时间。

//test.h
template<typename T>
void test_fun(T a)
{
}
//test1.cpp
test_fun(1);
//test2.cpp
test_fun(2);

这个问题可以用外部模板来避免,修改test1.cpp和test2.cpp的内容如下,先对模板进行显示实例化,然后在相同模板类型的调用处使用extern进行修饰。

//test1.cpp
template void test_fun<int>(int);
test_fun(1);
//test2.cpp
extern template void test_fun<int>(int);
test_fun(2);

局部和匿名实参作为模板参数
C++11同时支持了局部和匿名的类型作为模板参数,如下:

template<typename T>
class Testclass
{
};

template<typename T>
void test_fun(T a)
{
}

struct A{}a;               // 命名类型
struct{int i;} b;          // 匿名类型变量
typedef struct{int i;} B;  // 匿名类型

int main()
{
    struct C{} c;         // 局部命名类型
    Testclass<A> test1;   // C++98、C++11都编译通过
    Testclass<B> test2;   // C++11编译通过
    Testclass<C> test3;   // C++11编译通过

    test_fun(a);          // C++98、C++11都编译通过
    test_fun(b);          // C++11编译通过
    test_fun(c);          // C++11编译通过

    return 0;
}

下一篇:《深入理解C++11》笔记–构造函数

猜你喜欢

转载自blog.csdn.net/wizardtoh/article/details/80632699