之前遇到了一些关于模板特例化的问题,自己总结一下。

模板的特例化是C++新标准的一个特点,可以自定义某些模板的实现,比如在比较函数compare可以使用less<T>标准库模板比较string、int、char、指针等类型,但如果有const char*类型且比较字符串的字典大小时,就与之前的比较方式不同了:

#ifndef A_H
#define A_H#include <iostream>
#include <cstring>
using std::less;
template <typename T>
int compare(const T v1,const T v2)
{if (less<T>()(v1,v2)) {return -1;}else if (less<T>()(v2,v1)){return 1;}else{return 0;}
}template <>
inline int compare(const char *const a,const char *const b)
{return strcmp(a,b);
}#endif #include "a.h"
using std::cout;
using std::endl;int main()
{cout << compare(1,2) << endl;  cout << compare("123","asd") << endl;  return 0;
}

现在看上去没什么问题,并且只有这两个文件编译通过且正常运行,如果多了一个包含a.h的文件a.cpp:

#include "a.h"

这里只有一句,但包含了a.h文件表示将其模板函数的定义包含,且特例化的函数类似一个普通函数,则a.cpp、main.cpp包含多个相同函数的定义,因此在链接时有重定义问题。

解决方法:

使用内联inline声明特例化的模板,则某些函数的定义可以在多个文件包含(一些函数的实现可能不支持内联):

template <>
inline int compare(const char *a,const char *b)
{return strcmp(a,b);
}

另外一个是使用一个文件包含该头文件,让所有链接的文件只有一个特例化定义

第三个是定义普通同名函数,通过重载调用非模板函数(在参数匹配级别相同时,非模板重载函数优先调用)

// a.h
#ifndef A_H
#define A_H#include <iostream>
#include <cstring>
using std::less;
template <typename T>
int compare(const T v1,const T v2)
{if (less<T>()(v1,v2)){return -1;}else if (less<T>()(v2,v1)){return 1;}else{return 0;}
}int compare(const char *a,const char *b) ;// a.cpp
#include "a.h"int compare(const char *a, const char *b)
{std::cout << "const char*"<<std::endl;return strcmp(a,b);
}
// main.cpp 相同

如果有其他的方法请大家一起交流

转载于:https://blog.51cto.com/zmh009/1883801

C++模板的特例化编译为多重定义问题相关推荐

  1. 函数模板的特例化(专用化)以及类型含有const的特殊情况

    一.函数模板特例化: 1 #include <iostream> 2 #include <typeinfo>3 using namespace std;4 5 template ...

  2. C++ Primer 5th笔记(chap 16 模板和泛型编程)类模板部分特例化

    1. 类模板的部分特例化(partial specialization) 类模板的特例化不必为所有模板参数提供实参(可以只指定一部分而非所有模板参数, 或是参数的一部分而非全部特性).类模板的部分特例 ...

  3. 【深入理解C++】函数模板和类模板的特例化

    文章目录 1.函数模板的特例化 1.1 函数模板的全特化 1.2 函数模板不能偏特化 1.3 函数模板.函数模板的全特化.普通函数 2.类模板的特例化 2.1 类模板的全特化 2.2 类模板成员函数的 ...

  4. 类和函数模板以及特例化

    一.函数模板 1.定义 建立一个通用函数,它所用到的数据的类型(包括返回值类型.形参类型.局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据 ...

  5. 【C++模板】类模板的全部特例化和局部特例化(偏特化-partial specialization)

    前言 本专栏所有的文章都需要一定的基础知识.在文中对于基础的概念将会一带而过,或者在其他文章有讲,会贴出对应的链接而不再进行赘述. 目录 前言 类模板的Stack实现 类模板的全部特例化(偏特化) 写 ...

  6. C++模板与泛型编程:模板特例化

    文章目录 模板特例化 定义函数模板特例化 函数重载与模板特例化 类模板特例化 类模板部分特例化 特例化成员而不是类 模板特例化 ​ 编写单一模板,使之对任何可能的模板实参都是最合适的,都能实例化,这并 ...

  7. C++:51---重载与模板、模板特例化

    一.重载与模板 函数模板可以被另一个模板或一个普通非模板函数重载 如果涉及函数模板,则函数匹配规则会有以下的约束: ①对于一个调用,其候选函数包括所有模板实参推断成功的函数模板实例 ②候选的函数模板总 ...

  8. C++:19---重载与模板、模板特例化

    一.重载与模板 函数模板可以被另一个模板或一个普通非模板函数重载 如果涉及函数模板,则函数匹配规则会有以下的约束: 如果同样好的函数中只有一个是非模板函数,则选择此函数 如果同样好的函数中没有非模板函 ...

  9. 模板类的特例化(具体化)

    模板的基础知识: 模板的实例化 模板并不是真正的函数或类,它仅仅是编译器用来生成函数或类的一张"图纸".模板不会占用内存,最终生成的函数或者类才会占用内存.由模板生成函数或类的过程 ...

最新文章

  1. 小程序云开发获取手机号完整代码 云函数中网络请求第三方接口
  2. 懂得了这些才可以说学习Python入门了
  3. php where 优先,php – 使用WHERE选择所有内容
  4. 中国肠道大会 | 日程及嘉宾
  5. Android之如何获取网络类型并判断是否可用
  6. Java程序员考什么证可以镀金?
  7. 开课吧python好吗-开课吧9.9元学Python课程适合哪些人?开课吧靠谱吗?
  8. 解决Ubuntu14.04在外接显示器不能指定问题的最佳分辨率
  9. 从GCN中学习的信息熵
  10. 致初级开发的一封信:坚持写代码!
  11. 详解Paint的setColorFilter(ColorFilter filter)
  12. Juniper防火墙新手教程8:Juniper防火墙配置的导入及导出
  13. K8s运行dashboard命令启动报错:no endpoints available for service \kubernetes-dashboard\
  14. 堆栈的缓冲区溢出进不了系统_一文理解缓冲区溢出
  15. 基于速度学习机的局部感受野
  16. ApiCloud重新定义移动应用开发
  17. BrainOS —最像大脑的AI
  18. python 闲鱼_闲鱼上哪些商品抢手?Python 分析后告诉你
  19. docker防止fork炸弹
  20. Linux自动备份压缩MySQL数据库的实用方法

热门文章

  1. Net线程间通信的异步机制
  2. day04-视图/配置文件/静态文件的基本使用
  3. 数据流中的第k大元素的golang实现
  4. Java 文件上传下载管理器(控制台)
  5. 一步一步学lucene——(第四步:搜索篇)
  6. Javascript中计算脚本运行的时间
  7. 修改Android下的radioButton字体的颜色
  8. XAML实例教程系列 – 对象和属性
  9. netstat/nmap/netcat用法
  10. 细数网站成功赢利须具备的四大核心要素