1、基本概念
#include <iostream>
// 函数模板
template<typename T>
bool equivalent(const T& a, const T& b)
{
return !(a < b) && !(b < a);
}
// 类模板(.h)
template<typename T=int> // 默认参数
class bignumber
{
T _v;
public:
bignumber(T a) : _v(a) { }
inline bool operator<(const bignumber& b) const; // 等价于 (const bignumber<T>& b)
};
// 在类模板外实现成员函数(.cpp)
template<typename T>
bool bignumber<T>::operator<(const bignumber& b) const
{
return _v < b._v;
}
int main()
{
bignumber<> a(1), b(1); // 使用默认参数,"<>"不能省略
std::cout << equivalent(a, b) << '\n'; // 函数模板参数自动推导
std::cout << equivalent<double>(1, 2) << '\n';
std::cin.get(); return 0;
}
1.1 模板类
template <typename T1, typename T2>
struct Test
{
T1 t1;
T2 t2;
};
template <typename T, size_t size>
class Array
{
public:
Array();
T &at();
size_t size() const;
private:
T data_[size];
};
void Demo()
{
Array<int, 5> arr; // 实例化,并创建对象
arr.at(1) = 6;
}
1.2 模板函数
// 普通模板函数
template <typename T>
void show(const T &item)
{
std::cout << item << std::endl;
}
class Test
{
public:
// 模板成员函数
template <typename T>
void mem_func(const T &item) {}
};
// 模板lambda表达式(只能是全局变量承载)
template <typename T>
auto f = [](const T &item) {}
调用方法:
show<int>(5);
Test t;
t.mem_func<double>(5.1);
f<char>('A');
1.3 模板全局常量
// 用于引导模板全局常量的模板类(用于判断一个类型的长度是否大于指针)
template <typename T>
struct IsMoreThanPtr
{
static bool value = sizeof(T) > sizeof(void *);
};
// 全局模板常量
template <typename T>
constexpr inline bool IsMoreThanPtr_v = IsMoreThanPtr<T>::value;
1.4 变参
1.5 实例化
- 隐式实例化(implicit instantiation):当使用实例化的模板时自动地在当前代码单元之前插入模板的实例化代码,模板的成员函数一直到引用时才被实例化;
- 显式实例化(explicit instantiation):直接声明模板实例化,模板所有成员立即都被实例化;
1.6 可变参数
//变参模板函数,第一行为通用,第二行为具体声明
template<typename First, typename... Rest> class tuple;
template<typename... Params> void printf(const std::string &str_format, Params... parameters);
//变参模板类,第一行通用,第二行具体声明
template<typename... Values> class tuple;
tuple<int, std::vector<int>, std::map<<std::string>, std::vector<int>>> some_instance_name;
tuple<> some_instance_name; //0个实参
//变参个数,sizeof...与sizeof是两个不同的运算符
template<typename ...Args> struct SomeStruct {
static const int size = sizeof...(Args);
};
可变参数:
https://cppinsights.io/s/b78454ba
#include <tuple>
template<typename... Args>
void f(Args... args) {
std::tuple<Args...> tup = // 展开模板参数包
std::make_tuple(args...); // 展开函数参数包
}
int main()
{
f(1, "2", 3.0);
}
#include <tuple>
template<typename ... Args>
void f(Args... args)
{
std::tuple<Args...> tup = std::make_tuple(args... );
}
/* First instantiated from: insights.cpp:11 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void f<int, const char *, double>(int __args0, const char * __args1, double __args2)
{
std::tuple<int, const char *, double> tup = std::make_tuple(__args0, __args1, __args2);
}
#endif
int main()
{
f(1, "2", 3.0);
return 0;
}
c++17:
https://godbolt.org/z/v7PbYh6oP
https://godbolt.org/z/fG5sPE1c3
2、函数作为模板参数
2.1 function_traits
function_traits通过模板特化和可变参数模板来获取函数类型和返回类型
function_traits2 通过对函数特征的学习深入理解模板