c++11--变长模板

1.变长模板
1.1…变长模板定义
支持不限制数量的模板参数

// tuple是一个模板类
// 模板形参:可变数量的类型
template 
class tuple{}
tuple a;

// NonTypeVar是一个模板类
// 模板形参:可变数量的int类型数值
template
class NonTypeVar{};
NonTypeVar<1, 0, 2> aa;

1.2.变长模板使用
(1).使用模板参数包

#include 
// B是一个模板类
// 模板形参:两个类型
template
class B { 
};

// B是一个特化的模板类
// 模板形参:int,double
template <>
class B {
public:
    B() {
    	printf("B\n");
    }
};

// Temp是一个模板类
// 模板形参:可变数量的类型
// A...代表对typename... A为代表的部分的一个引用。
template
class Temp:private B {
};

// 这个xy将私有继承B
Temp xy;
int main(){
    return 0;
}

在这里插入图片描述
(2).对可变参数模板结合模板特化展开

#include 

// tuple是一个模板类
// 模板形参:可变个数类型
template
class tuple{
public:
    tuple(){
        printf("normal\n");
    }
};

// tuple是一个特化模板类
// 模板形参:可变个数类型。从第二到最后一个类型可通过Tail...来整体引用
template
class tuple:private tuple{
public:
    tuple(){printf("sizeof_%d\n", sizeof(Head));}
    Head h;
};

// tuple<>是一个特化模板类
// 模板形参:空
template<>
class tuple<>{
public:
    tuple(){
        printf("null\n");
    }
};

tuple a;
int main(){
    return 0;
}

c++11--变长模板_第1张图片
另一个等价实例

#include 
using namespace std;

template
struct Multiply{};

template
struct Multiply{
    static const long val = first * Multiply::val;
};

template<>
struct Multiply<>{
    static const long val = 1;
};

int main(){
    cout << Multiply<2,3,4,5>::val << endl;
    return 0;
}

在这里插入图片描述
(3).基于变长模板的模板函数

// f是一个模板函数
// 函数形参:可变个数类型的变量
template
void f(T... args){
}

int main(){
	f(1, 1.0);//实例化为f(int a, double b)
	f(1);//实例化为f(int)
}

利用模板参数包,函数参数包可实现c的变长函数的一个实例

#include 
#include 
using namespace std;

void Printf(const char* s){
    while(*s){
        if(*s == '%' && *++s != '%'){
            throw runtime_error("invalid format string: missing arguments");
        }
        cout << *s++;
    }
}

// Printf是一个模板函数
// 函数形参:首个参数必须是const char*,第二个参数必须是某个类型,第三到最后为可变数量个类型
template
void Printf(const char* s, T value, Args... args){
    while(*s){
        if(*s == '%' && *++s != '%'){
            cout << value;
            return Printf(++s, args...);
        }
        cout << *s++;
    }
    throw runtime_error("extra arguments provided to Printf");
}

int main(){
    Printf("hello %s\n", string("world"));
    return 0;
}

c的可变参数函数printf必须依赖对格式化字符串的解析,来提取每个可变参数。
借助可变参数模板,可以不依赖格式化字符串,借助模板类型推导,可变参数包来依次得到每个模板参数的类型和实参。

(4).使用参数包时允许添加修饰符

#include 
using namespace std;
template
void DummyWrapper(T... t){
}

template
T pr(T t){
    cout << t;
    return t;
}

// VTPrint是一个模板函数
// 函数形参:可变数量的类型
template
void VTPrint(A... a){
	// 通过a...可以整体引用A... a
	// 通过pr(a)...,相当于整体引用A... a时,对其中每个元素t引用的是pr(t)
    DummyWrapper(pr(a)...);
}

int main(){
    VTPrint(1, ", ", 1.2, ", abc\n");
    cout << endl;
    return 0;
}

c++11--变长模板_第2张图片
打印顺序不符合实参顺序,是由于形参求值顺序并非从左到右引起的。

你可能感兴趣的:(1.3.语言-C++11,变长模板类型,变长模板函数,参数包,模板特化)