可变参数模版
- 谈的模板包含类模板,函数模板
- 变化的是模板参数
参数个数以及类型是变化的,通过逐渐递减参数个数来实现递归定义
- 例子1
void printX(){} //函数2
//函数1
template<typename T,typename...Types>
void printX(const T& firstArg,const Types&...args){
//如果想知道参数个数 sizeof...(args)
cout<<firstArg<<end;
printX(args);
}
//函数3 可以和1共存,因为函数1比较特化,所以可以调用到函数1,只是函数3永远不会被调用
template<typename...Types>
void printX(const Types&...args)
{}
printX(7.5,bitset<16>(377),42);
2.例子2 使用可变参数模板实现printf
void printf(const char*s){
while(*s)
{
if(*s== '%' && *(++s)!= '%')
throw std::runtime_error("invalid format error: 参数不够");
std::cout<<*s++;
}
}
template<typename T,typename...Args>
void printf(const char*s,T value,Args...args)
{
while(*s){
if(*s == '%'&&*(++s)!='%')
{
cout<<value;
printf(++s,args...);
return;
}
std::cout<<*s++;
}
throw std::logic_error("额外的参数");
}
3.例子3,设计max函数
//如果比较的是的是同一种类型,可以使用initializer Lists
template<typename T>
inline T max(initializer_list<T> ilist)
{
return *max_element(ilist.begin(),ilist.end());
}
cout<<max({4,6,1});
//上述接口不理想,使用可变参数模板来实现
int Max(int n){
return n;
}
template<typename ...Args>
int Max(int n,Args...args)
{
return std::max(n,Max(args));
}
cout<<Max(4,6,1);
4.例子4,设计打印tuple
using namespace std;
template<int IDX,int MAX,typename...Args>
struct PRINT_TUPLE
{
static void print(ostream& os, const tuple<Args...>& t) {
os << get<IDX>(t) << (IDX + 1 == MAX ? "" : ",");
PRINT_TUPLE<IDX + 1, MAX, Args...>::print(os, t);
}
};
//传递进来的模板参数还是为3个,但是类型一样在template这里合二为一
template<int MAX,typename...Args>
struct PRINT_TUPLE<MAX, MAX,Args...>
{
static void print(ostream& os, const tuple<Args...>& t) {
}
};
template <typename...Args>
ostream& operator<<(ostream& os, const tuple<Args...>& t) {
os << "[";
PRINT_TUPLE<0, sizeof...(Args), Args...>::print(os, t);
return os << "]";
};
void test() {
cout << make_tuple(7.5, string("hello"), 33);
};
5.例子5,递归的继承
//递归的继承
template<typename...Values> class Tuple;
template<> class Tuple<> {};
template<typename Head,typename...Tail>
class Tuple<Head, Tail...>
:private Tuple<Tail...>
{
//typedef Tuple<Tail...> inherrited;
using inherrited = Tuple<Tail...>;
private:
Head m_head;
public:
Tuple() {}
Tuple(Head v,Tail...vTail):
m_head(v), inherrited(vTail...){}
//这个写法在编译不过
//typename Head::type head() { return m_head; }
//auto head() { return m_head; }
//auto head()-> decltype(m_head) { return m_head; }
inherrited& tail() { return *this; }
Head head() { return m_head; }
};
void test() {
Tuple<int,string> aaa(41,string("ggg"));
cout << aaa.tail().head() << endl;
}
6.例子6,递归的组合
template<typename...Values> class tup;
template<>class tup<> {};
template<typename Head,typename...Tail>
class tup<Head, Tail...>
{
using composited = tup<Tail...>;
protected:
composited m_tail;
Head m_head;
public:
tup(){}
tup(Head v,Tail...vTail)
:m_tail(vTail...),m_head(v){}
Head head() { return m_head;}
composited& tail() { return m_tail; }
};
void test() {
tup<int, string> aaa(41, string("hhh"));
cout << aaa.tail().head() << endl;
}