当前位置: 移动技术网 > IT编程>开发语言>C/C++ > C++之模板元编程

C++之模板元编程

2018年03月17日  | 移动技术网IT编程  | 我要评论

星际猎王,中国球王txt,超级修圣传奇

通过举例详细介绍了模板的模板参数,模板特例化,模板实例化以及编译链接等模板基础知识。

本文主要分析文章中的模板元编程例子:

首先复述一下模板元编程:

从编程范型(programming paradigm)上来说,C++ 模板是函数式编程(functional programming),它的主要特点是:函数调用不产生任何副作用(没有可变的存储),用递归形式实现循环结构的功能。C++ 模板的特例化提供了条件判断能力,而模板递归嵌套提供了循环的能力,这两点使得其具有和普通语言一样通用的能力(图灵完备性)。

从编程形式来看,模板的“<>”中的模板参数相当于函数调用的输入参数,模板中的 typedef 或 static const 或 enum 定义函数返回值(类型或数值,数值仅支持整型,如果需要可以通过编码计算浮点数),代码计算是通过类型计算进而选择类型的函数实现的(C++ 属于静态类型语言,编译器对类型的操控能力很强)

模板下的控制结构:

template<bool
c,
typename
Then,
typename
Else>
class
IF_
{
};

template<typename
Then,
typename
Else>

class
IF_<true,
Then,
Else>
{
public:
typedef
Then
reType;
};

template<typename
Then,
typename
Else>

class
IF_<false,Then,
Else>
{
public:
typedef
Else
reType;
};

 

//
 隐含要求: Condition 返回值 ret,Statement 有类型 Next

template<template<typename>
class
Condition,
typename
Statement>

class
WHILE_
{

    template<typename
Statement>
class
STOP
{
public:
typedef
Statement
reType;
};

public:

    typedef
typename

        IF_<Condition<Statement>::ret,

        WHILE_<Condition,
typename
Statement::Next>,

        STOP<Statement>>::reType::reType

    reType;

};




template<int
n,
int
e>

class
sum_pow
{

    template<int
i,
int
e>
class
pow_e{
public:
enum{
ret=i*pow_e<i,e-1>::ret
};
};

    template<int
i>
class
pow_e<i,0>{
public:
enum{
ret=1
};
};

    //
 计算 i^e,嵌套类使得能够定义嵌套模板元函数,private 访问控制隐藏实现细节

    template<int
i>
class
pow{
public:
enum{
ret=pow_e<i,e>::ret
};
};

    template<typename
stat>

    class
cond
{
public:
enum{
ret=(stat::ri<=n)
};
};

    template<int
i,
int
sum>

    class
stat
{
public:
typedef
stat<i+1,
sum+pow<i>::ret>
Next;

                        
enum{
ri=i,
ret=sum
};
};

public:

    enum{
ret
=
WHILE_<cond,
stat<1,0>>::reType::ret
};

};

 

int
main()
{

    std::cout
<<
sum_pow<10,
2>::ret
<<
'\n';

    std::cin.get();
return
0;

}

//代码解析:

sum_pow<10,2>利用模板参数相当于函数调用的输入参数。::ret是函数的返回值,用enum或者static const定义的变量。1.函数调用WHILE_条件函数;2.WHILE_条件函数调用其返回类型reType;3. WHILE_条件函数调用IF_函数;4.IF_函数需要判断cond的布尔值;5.由于WHILE_函数首先执行stat<1,0>函数;6.stat<1,0>会设置ri=1; 7.cond函数的返回值为true;8. IF_函数返回THEN类型,即在此执行WHILE_函数。整个模板的执行过程就是1+ 2*2 + 3*3* +....+10*10= 385

在讲元容器之前,我们先来看看伪变长参数模板,一个可以存储小于某个数(例子中为 4 个)的任意个数,任意类型数据的元组(tuple)的例子如下:

#include <iostream>

 

class
null_type
{};
//
 标签类,标记参数列表末尾

template<typename
T0,
typename
T1,
typename
T2,
typename
T3>

class
type_shift_node
{

public:

    typedef
T0
data_type;

    typedef
type_shift_node<T1,
T2,
T3,
null_type>
next_type;
//
 参数移位了

    static
const
int
num
=
next_type::num
+
1;
//
 非 null_type 模板参数个数

    data_type
data;
//
 本节点数据

    next_type
next;
//
 后续所有节点数据

    type_shift_node()
:data(),
next()
{
}
//
 构造函数

    type_shift_node(T0
const&
d0,
T1
const&
d1,
T2
const&
d2,
T3
const&
d3)

        :data(d0),
next(d1,
d2,
d3,
null_type())
{
}
//
 next 参数也移位了

};

template<typename
T0>
//
 特例,递归终止

class
type_shift_node<T0,
null_type,
null_type,
null_type>
{

public:

    typedef
T0
data_type;

    static
const
int
num
=
1;

    data_type
data;
//
 本节点数据

    type_shift_node()
:data(),
next()
{
}
//
 构造函数

    type_shift_node(T0
const&
d0,
null_type,
null_type,
null_type)
:
data(d0)
{
}

};

//
 元组类模板,默认参数 + 嵌套递归

template<typename
T0,
typename
T1=null_type,
typename
T2=null_type,

        
typename
T3=null_type>

class
my_tuple
{

public:

    typedef
type_shift_node<T0,
T1,
T2,
T3>
tuple_type;

    static
const
int
num
=
tuple_type::num;

    tuple_type
t;

    my_tuple(T0
const&
d0=T0(),T1
const&
d1=T1(),T2
const&
d2=T2(),T3
const&
d3=T3())

        :
t(d0,
d1,
d2,
d3)
{
}
//
 构造函数,默认参数

};

 

//
 为方便访问元组数据,定义 get<unsigned>(tuple) 函数模板

template<unsigned
i,
typename
T0,
typename
T1,
typename
T2,
typename
T3>

class
type_shift_node_traits
{

public:

    typedef
typename

        type_shift_node_traits<i-1,T0,T1,T2,T3>::node_type::next_type
node_type;

    typedef
typename
node_type::data_type
data_type;

    static
node_type&
get_node(type_shift_node<T0,T1,T2,T3>&
node)

    {
return
type_shift_node_traits<i-1,T0,T1,T2,T3>::get_node(node).next;
}

};

template<typename
T0,
typename
T1,
typename
T2,
typename
T3>

class
type_shift_node_traits<0,
T0,
T1,
T2,
T3>
{

public:

    typedef
typename
type_shift_node<T0,T1,T2,T3>
node_type;

    typedef
typename
node_type::data_type
data_type;

    static
node_type&
get_node(type_shift_node<T0,T1,T2,T3>&
node)

    {
return
node;
}

};

template<unsigned
i,
typename
T0,
typename
T1,
typename
T2,
typename
T3>

typename
type_shift_node_traits<i,T0,T1,T2,T3>::data_type

get(my_tuple<T0,T1,T2,T3>&
tup)
{

    return
type_shift_node_traits<i,T0,T1,T2,T3>::get_node(tup.t).data;

}

 

int
main(){

    typedef
my_tuple<int,
char,
float>
tuple3;

    tuple3
t3(10,
'm',
1.2f);

    std::cout
<<
t3.t.data
<<
' '

              <<
t3.t.next.data
<<
' '

              <<
t3.t.next.next.data
<<
'\n';

    std::cout
<<
tuple3::num
<<
'\n';

    std::cout
<<
get<2>(t3)
<<
'\n';
//
 从 0 开始,不要出现 3,否则将出现不可理解的编译错误

    std::cin.get();
return
0;

}




//变长参数利用的就是循环,通过将参数移位,然后设定null_type的方式实现变长参数

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网