设为首页 加入收藏

TOP

C++11模版元编程(三)
2015-11-21 01:03:04 来源: 作者: 【 】 浏览:11
Tags:模版 编程
等算法。实现这些算法需要结合type_traits或其它C++11特性,下面来看看这些编译期算法是如何实现的。
?
  编译期从一个整形序列中获取最大值:
?
?
//获取最大的整数
template
struct IntegerMax;
?
template
struct IntegerMax : std::integral_constant
{
};
?
template
struct IntegerMax : std::integral_constant= arg2 ? IntegerMax::value :
? ? IntegerMax::value >
{
};
?
  这个IntegerMax的实现用到了type_traits中的std::integral_const,它在展开参数包的过程中,不断的比较,直到所有的参数都比较完,最终std::integral_const的value值即为最大值。它的使用很简单:
?
cout << IntegerMax<2, 5, 1, 7, 3>::value << endl; //value为7
?
  我们可以在IntegerMax的基础上轻松的实现获取最大内存对齐值的元函数MaxAlign。
?
  编译期获取最大的align:
?
?
template
struct MaxAlign : std::integral_constant::value...>::value>{};
cout << MaxAlign::value << endl; //value为8
? ? 编译判断是否包含了某种类型:
template < typename T, typename... List >
struct Contains;
?
template < typename T, typename Head, typename... Rest >
struct Contains
? ? : std::conditional< std::is_same::value, std::true_type, Contains> ::type{};
?
template < typename T >
struct Contains : std::false_type{};
用法:cout<::value<
?
  这个Contains的实现用到了type_traits的std::conditional、std::is_same、std::true_type和std::false_type,它的实现思路是在展开参数包的过程中不断的比较类型是否相同,如果相同则设置值为true,否则设置为false。
?
? ? ? ? 编译期获取类型的索引:
?
?
template < typename T, typename... List >
struct IndexOf;
?
template < typename T, typename Head, typename... Rest >
struct IndexOf
{
? ? enum{ value = IndexOf::value+1 };
};
?
template < typename T, typename... Rest >
struct IndexOf
{
? ? enum{ value = 0 };
};
?
template < typename T >
struct IndexOf
{
? ? enum{value = -1};
};
?
  用法:cout<< IndexOf::value<
?
  这个IndexOf的实现比较简单,在展开参数包的过程中看是否匹配到特化的IndexOf,如果匹配上则终止递归将之前的value累加起来得到目标类型的索引位置,否则将value加1,如果所有的类型中都没有对应的类型则返回-1;
?
  编译期根据索引位置查找类型:
?
?
template
struct At;
?
template
struct At
{
? ? using type = typename At::type;
};
?
template
struct At<0, T, Types...>
{
? ? using type = T;
};
? ? 用法:
using T = At<1, int, double, char>::type;
? ? cout << typeid(T).name() << endl; //输出double
?
  At的实现比较简单,只要在展开参数包的过程中,不断的将索引递减至0时为止即可获取对应索引位置的类型。接下来看看如何在编译期遍历类型。
?
?
template
void printarg()
{
? ? cout << typeid(T).name() << endl;
}
?
template
void for_each()?
{
? ? std::initializer_list{(printarg(), 0)...};
}
用法:for_each();//将输出int double
?
  这里for_each的实现是通过初始化列表和逗号表达式来遍历可变模板参数的。
?
  可以看到,借助可变模板参数和type_traits以及模板偏特化和递归等方式我们可以实现一些有用的编译期算法,这些算法为我们编写应用层级别的代码奠定了基础,后面模板元编程的具体应用中将会用到这些元函数。
?
  C++11提供的tuple让我们编写模版元程序变得更灵活了,在一定程度上增强了C++的泛型编程能力,下面来看看tuple如何应用于元程序中的。
?
5.tuple与模版元
?
  C++11的tuple本身就是一个可变模板参数组成的元函数,它的原型如下:
?
template
class tuple;
?
  tuple在模版元编程中的一个应用场景是将可变模板参数保存起来,因为可变模板参数不能直接作为变量保存起来,需要借助tuple保存起来,保存之后再在需要的时候通过一些手段将tuple又转换为可变模板参数,这个过程有点类似于化学中的“氧化还原反应”。看看下面的例子中,可变模板参数和tuple是如何相互转换的:
?
?
//定义整形序列
template
struct IndexSeq{};
?
//生成整形序列
template
struct MakeIndexes : MakeIndexes{};
?
template
struct MakeIndexes<0, indexes...>{
? ? typedef IndexSeq type;
};
?
template
void printargs(Args... args){
? ? //先将可变模板参数保存到tuple中
? ? print_helper(typename MakeIndexes::type(), std::make_tuple(args...));
}
?
template
void print_helper(IndexSeq, std::tuple&& tup){
? ? //再将tuple转换为可变模板参数,将参数还原回来,再调用print
? ? print(std::get(tup)...);?
}
template
void print(T t)
{
? ? cout << t << endl;
}
?
template
void print(T t, Args... args)
{
? ? print(t);
? ? print(args...);
}
?
  用法:printargs(1, 2.5, “test”); //将输出1 2.5 test
?
  上面的例子print实际上是输出可变模板参数的内容,具体做法是先将可变模板参数保存到tuple中,然后再通过元函
首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇UVALive6814 Lexicography 下一篇UVA - 1616 Caravan Robbers 二分..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: