4_4_类成员模板函数.cpp
#include "hjcommon.hpp"
#include "4_4/Test.h"
using namespace std;
HJ_NS_USING
//extern template Test<int>; // vs2017编译器此方式能编译通过, Ubuntu 18 编译报错。
extern template void tempFunc(float a, float b); // 显式实例化与实例化声明对于函数模板,在Ubuntu 18 能成功编译,且运行正常。
HJ_NS_BEGIN
template<typename A>
class Demo
{
public:
template<typename B, typename C> Demo(B b, C c);
template<typename D> void func(D c) {} // 类的成员模板函数,注意:类的成员模板函数不能是虚函数,否则编译报错
};
template<typename A> // 成员模板函数实现处写法:先写模板类的模板,再写成员模板函数的模板
template<typename B, typename C> // 模板构造函数建议与声明写在一起,否则编译器可能会编译报错。 在Ubuntu 18 编译会报此构造函数未定义。。
Demo<A>::Demo(B b, C c) // 引申:所有类型的模板函数的声明与实现都建议写在同一个文件里,或者声明时就实现。
{
cout << "Demo. b=" << b << ",c=" << c << endl;
}
// 我们知道:在代码中Demo<int> d;定义这么一句,就表示告诉编译器实例化一个 Demo<int> 类,而且每个cpp文件都是独立编译的。
// 当如果在有多cpp文件中都这么 Demo<int> d; 定义了的话,编译器会生成多份 Demo<int> 类,c++11中引入显式实例化与实例化声明解决此问题
//template Demo<int>; // 显式实例化类模板,只需要显式实例化一个。建议写在源文件开头的位置
//extern template Demo<int>; // 实例化声明类模板,供其他cpp文件中使用,表示此类在其他cpp中实例化过了,不要重复实例化。建议写在源文件开头的位置
//template<typename T>
//void tempFunc(T t1, T t2) { cout << "函数模板显式实例化与实例化声明. t1=" << t1 << ",t2=" << t2 << endl; }
//template void tempFunc(int a, int b); // 函数模板一样用此方式显式实例化与实例化声明
//extern template void tempFunc(int a, int b);
// 建议:不要使用显式实例化模板与实例化声明模板,不同编译器,不一定能正常编译通过
HJ_NS_END
int main_2_4_4(int argc, char *argv[])
{
Demo<int> d(1, "d"); // 可以
// Demo<int> d2<int, String>(1, ""); // 不可以
d.func('c'); // 可以
d.func<char>('c'); // 可以
// 显式实例化模板与实例化声明模板 测试
Test<int> test(1, "t");
tempFunc(1.1f, 2.3f);
// 建议:由于不同编译器的行为不同,显式实例化与实例化声明建议不要使用。
return 0;
}
4_5_类型模板.cpp
#include "hjcommon.hpp"
#include <map>
using namespace std;
HJ_NS_USING
// 加入要实现一个功能: 定义一个key为string,value值为随意的map。 c++98实现(使用typedef):
template<typename V>
struct map_s_98 // c++98中必须使用一个类来包装
{
typedef std::map<String, V> type; // 定义别名
};
// c++11实现(使用using定义模板类型):
template<typename V>
using map_s_11 = std::map<String, V>; // c++11使用using直接定义类型模板,using在定义别名的时候是包含了typedef所有功能的,功能比typedef更强大
template<typename T>
using FuncPoint = int(*)(T, T); // 使用using定义类型模板,也可以称为模板别名
static int add(int a, int b) { return a+b; }
int main_2_4_5(int argc, char *argv[])
{
map_s_98<int>::type map1; // get
map1.insert({"one", 1}); // 需要 {} 。。
map_s_11<String> map2; // get
map2.insert({"two", "2"});
FuncPoint<int> fp = add;
cout << fp(1, 3) << endl;
return 0;
}