标签:style blog http io ar color os 使用 sp
1 #include <iostream> 2 #include <vector> 3 4 template <class IN> // 这一部分做成静态库 5 void PrintByIterator(IN begin, IN end) 6 { 7 while (begin != end) 8 { 9 std::cout <<*begin <<" "; 10 ++begin; 11 } 12 std::cout <<std::endl; 13 } 14 15 int main() 16 { 17 int testArr[5] = {1, 3, 5, 9, 2}; 18 PrintByIterator(testArr, testArr + 5); 19 return 0; 20 }
为了便于笔记主题的清晰演示,上面给出了一个简单的代码示例,通过它来演示本笔记所要达成的制作函数模板静态库的目的。如上代码片段当中的函数模板PrintByIterator,如果能够将其制作成为一个静态库,就可以避免在实现其他函数的同时重新编写或者复制拷贝的工作。当然,也存在有其它需求场景。
1 // 静态库工程,包含PrintByIterator模板定义 2 3 #include <iostream> 4 template <class IN> 5 void PrintByIterator(IN begin, IN end) 6 { 7 while (begin != end) 8 { 9 std::cout <<*begin <<" "; 10 ++begin; 11 } 12 std::cout <<std::endl; 13 }
1 // 测试工程 - cprint.h 2 3 #ifndef __CPRINT_H_ 4 #define __CPRINT_H_ 5 6 template <class IN> 7 void PrintByIterator(IN begin, IN end); 8 9 #endif // __CPRINT_H_ 10 11 12 // 测试工程 - main.cpp 13 #include <iostream> 14 #include "cprint.h" 15 int main() 16 { 17 int testArr[5] = {1, 3, 5, 9, 2}; 18 PrintByIterator(testArr, testArr + 5); 19 return 0; 20 }
然而,如上的代码组织方式,在编译工程的时候会出现如下的错误提示:
2.1 重温“静态库”
2.2 模板编译的特殊性
在包含编译模型当中,编译器必须看到所有模板的定义。一般而言,可以通过在声明函数模板的头文件中添加一条#include指令将模板定义包含到头文件中。
在分离编译模型中,必须启用export关键字来跟踪相关的模板定义。export关键字能够指明给定的定义可能会需要在其他文件中产生实例化。
方式一:
1 // cprint.h 2 #ifndef __CPRINT_H_ 3 #define __CPRINT_H_ 4 template <class IN> 5 void PrintByIterator(IN begin, IN end) 6 { 7 while (begin != end) 8 { 9 std::cout <<*begin <<" "; 10 ++begin; 11 } 12 std::cout <<std::endl; 13 } 14 #endif // __CPRINT_H_ 15 16 // main.cpp 17 #include <iostream> 18 #include <vector> 19 #include "cprint.h" 20 21 int main() 22 { 23 int testArr[5] = {1, 3, 5, 9, 2}; 24 PrintByIterator(testArr, testArr + 5); 25 26 return 0; 27 }
这是第一种方式,也即是将函数模板的实现放在头文件当中。这个时候类型的推演和int *类型函数的生成可以统一被视作一个“实例化”的过程。
方式二:
1 // cprint.h 2 #ifndef __CPRINT_H_ 3 #define __CPRINT_H_ 4 5 #include "cprint.cpp" 6 7 #endif // __CPRINT_H_ 8 9 // cprint.cpp 10 #include <iostream> 11 12 template <class IN> 13 void PrintByIterator(IN begin, IN end) 14 { 15 while (begin != end) 16 { 17 std::cout <<*begin <<" "; 18 ++begin; 19 } 20 std::cout <<std::endl; 21 } 22 23 // main.cpp 24 #include <iostream> 25 #include <vector> 26 #include "cprint.h" 27 28 int main() 29 { 30 int testArr[5] = {1, 3, 5, 9, 2}; 31 PrintByIterator(testArr, testArr + 5); 32 return 0; 33 }
这种方式在头文件当中包含函数模板的实现文件,与第一种方式实质是一样的,也就是对于函数模板的使用者来说,它可以同时看见函数的声明与定义。
方式三:
1 // cprint_ins.cpp 2 #include <vector> 3 #include "cprint.cpp" 4 5 using std::vector; 6 7 template void PrintByIterator<int *>(int * a, int * b); 8 9 10 // cprint.cpp 11 #include <iostream> 12 13 template <class IN> 14 void PrintByIterator(IN begin, IN end) 15 { 16 while (begin != end) 17 { 18 std::cout <<*begin <<" "; 19 ++begin; 20 } 21 std::cout <<std::endl; 22 }
1 // cprint.h 2 #ifndef __CPRINT_H_ 3 #define __CPRINT_H_ 4 5 template <class IN> 6 void PrintByIterator(IN begin, IN end); 7 8 #endif // __CPRINT_H_ 9 10 // main.cpp 11 #include <iostream> 12 #include <vector> 13 #include "cprint.h" 14 15 int main() 16 { 17 int testArr[5] = {1, 3, 5, 9, 2}; 18 PrintByIterator(testArr, testArr + 5); 19 return 0; 20 }
这种方式最开始看起来比较怪异,但也是本文最终所选定的最终方案,通过对它们的合理组织,便可以使得在链接阶段提供针对int *类型函数的实例化代码。其实现是通过在cprint_ins.cpp当中已经将模板PrintByIterator进行了显示的实例化操作,所以可以将它们作为库的形式提供,在链接阶段也就可以提供针对int *的实例化版本。如此便可使得静态库的制作得以实现。
标签:style blog http io ar color os 使用 sp
原文地址:http://www.cnblogs.com/yuxin2012/p/4130413.html