c++外部模板

240 篇文章 100 订阅
10 篇文章 0 订阅

一、什么是外部模板

模板的优势估计很多人都知道,但是模板的劣势也有不少,其中,代码膨胀就是其中之一(其它还有不易理解、不易调试等)。在实际情况中可能会有下面这种情况:

//tempFun.h
#pragma once

template<typename T,typename N>
T Add(T t, N n)
{
    return t + n;
}
//test.h
#pragma once
void First(int a,int b);
void Second(int a,int b);

//first.cpp
#include "iostream"
#include "tempFun.h"
#include "test.h"

void First(int a, int b)
{
    std::cout << Add(a,b) << std::endl;
}
//second.cpp
#include "iostream"
#include "tempFun.h"
#include "test.h"

void Second(int a, int b)
{
    std::cout << Add(a, b) << std::endl;
}
//main.cpp
#include "test.h"
#include <Windows.h>

int main()
{
    First(10,1);
    Second(11,2);
    system("pause");
  return 0;
}

上面的示例代码非常简单,但可以说明一个问题,在上一篇中提到过,c++的编译是以CPP为单元进行的,模板如果不使用就不会生成代码,那么如果在两个CPP文件中使用一样的数据类型会产生什么样的情况呢?比如上在这种情形,都是int类型,只是数据略有不同。答案是编译器肯定会生成两个完全相同的函数。然后在后续的过程中(包含链接等)会通过技术手段去除重复的代码,来实现单一副本。但是,扩展开来,如果一个工程非常大,编译器等经常做类似的工作,对生成效率的影响,估计可以想象的到。
学习c++/c语言的人,都会接触到extern关键字,知道一个全局变量可以通过其来进行外部声明。同样,在模板中,也可以使用这种方式。在c++11中引用了外部模板,就是通过这个关键字来解决这个问题的。

二、外部模板使用

在c++11中引入的外部模板,类似于extern一个全局变量的编译链接过程,如果发现这个关键字,就不再本地再来一份生成代码了。这样,就减少了前面提到的单一副本的处理过程了。看一个实例:

//其它类似,只修改使用的两个CPP
//first.cpp
#include "iostream"
#include "tempFun.h"
#include "test.h"

template int Add<int,int>(int,int);
void First(int a, int b)
{
    std::cout << Add(a,b) << std::endl;
}
//second.cpp
#include "iostream"
#include "tempFun.h"
#include "test.h"
extern template int Add<int,int>(int,int);
void Second(int a, int b)
{
    std::cout << Add(a, b) << std::endl;
}

上面的代码可以看出,其实是利用了显示实例化来实现这个问题,在以前的文章中说过,显示实例化只能一次,而且要放到CPP文件中,这里与之类似。首先在一个编译单元中将其显示实例化,然后在另外一个编译单元中使用extern关键字来声明其它单元中已经生成了这个代码。不过和全局变量相同,必须保证有实际的定义之处,否则编译会报链接错误。
需要注意的是,在一些IDE的开发环境中,会发现extern部分的函数会提示找不到实现,这是因为模板需要在编译期才会生成相关的实现代码,恰恰说明了上面的问题。如果大家有兴趣,也可以自己实验一番。
外部模板的使用有一些限制场景:
1、可以用于类内的静态函数,而不能用于全局的静态函数。
2、目前对内联的支持看编译器的实现。
3、外部模板只支持类成员而不支持类本身。

三、总结

其实从实际情况来看,决大多数的工程其实对这个外部模板是不感冒的,因为,其工程的大小可控。这就使得这个东西变成了鸡肋,所以说,对其的使用,还是根据自己的实际的情况来处理。说的直白一些,就是平衡效率和修改使用的工作量。
《2019-10-13 09:27》

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值