类模板
类模板的定义和声明
1. 定义
template <typename T>
class B
{
};
2. 声明
template <typename T>
class B;
3. 要点
- 翻译单元级一处定义原则
- 类模板不是类,在被调用时实例化
4. 类模板内定义成员函数
- 类模板中定义成员函数
注意:类内部使用类名时不用B{},可以直接B{}
// 类内定义成员函数:
template <typename T>
class B
{
public:
void fun1(T x)
{
}
void fun2()
{
B{}
}
};
// 类外定义成员函数:
template <typename T>
void B<T>::fun()
{
}
- 类的成员函数模板
//类内定义:
class B
{
public:
template<typename T>
void fun()
{
}
};
//类外定义:
class B
{
public:
template <typename T2>
void fun();
};
template <typename T>
void B::fun()
{
}
int main()
{
B a;
a.fun<int>(); //调用时实例化
}
- 类模板的成员函数模板
//类内定义:
template <typename T>
class B
{
public:
template <typename T2>
void fun()
{
T x;
T2 y;
}
};
//类外定义:
template <typename T>
class B
{
public:
template <typename T2>
void fun();
};
template <typename T>
template <typename T2>
void B<T>::fun()
{
}
int main()
{
B<int> x;
x.fun<float>();
}
- 类模板的友元函数
template <typename T>
class B
{
public:
friend void fun(B input)
{
std::cout<<input.x<<std::endl;
}
int x;
};
int main()
{
B<int> val;
fun(val);
}
类模板的实例化控制
template
class B<int>; //实例化B
template
void B<double>::fun(); //实例化B的一个成员函数
类模板的特化
- 类模板的特化可引入完全不同的内部成员
template <typename T>
strcut B
{
void fun()
{
}
};
tempalte <>
struct B<int>
{
void fun2()
{
}
};
2. 类模板可以部分特化
非常重要
- 基础操作:
template <typename T1,typename T2>
struct B
{
};
template<typename T2>
struct V<int,T2>
{
};
//也可以这样
template<typename T2>
struct V<int,T2&>
{
};
- 高级操作(结合变长模板)
template <typename... T>
class Cont;
template <typename T>
struct B
{
};
template<typename T1,typename T2,typename T3>
struct B<Cont<T1,T2,T3>>
{
};
总结: 模板部分特化,特化的部分要看struct B<…>,与template<…>关系不大
类模板的实参推导(C++17引入)
- 通过构造函数
template <typename T>
struct B
{
B(T input)
{}
};
int main()
{
B x(3);
}
- 用户自定义推导指引
cppreference_用户自定义推导指引
// 模板的声明
template<class T> struct container {
container(T t) {}
template<class Iter> container(Iter beg, Iter end);
};
// 额外推导指引
template<class Iter>
container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
// 使用
container c(7); // OK:用隐式生成的指引推出 T=int
std::vector<double> v = { /* ... */};
auto d = container(v.begin(), v.end()); // OK:推出 T=double
container e{5, 6}; // 错误:无 std::iterator_traits<int>::value_type
- C++17前,可以用函数模板实参推导来辅助推导
#include <utility>
int main()
{
std::pair(1,0.5) //C++17之后
}
#include <utility>
template <typename T1,typename T2>
std::pair<T1,T2> make_pair(T1 a,T2 b)
{
return pair<T1,T2>(a,b);
}
int main()
{
std::pair(1,0.5) //C++17之前会编译错误
auto x=make_pair(1,0.5) //函数模板辅助推导
}
|