设为首页 加入收藏

TOP

C++11模版元编程(二)
2015-11-21 01:03:04 来源: 作者: 【 】 浏览:17
Tags:模版 编程
typedef std::conditional::type A; ? ? ? ? ? ? ? // int
? ? typedef std::conditional::type B; ? ? ? ? ? ? ?// float
?
? ? typedef std::conditional<(sizeof(long long) >sizeof(long double)),
? ? long long, long double>::type max_size_t;
?
? ? cout<
}
?
  另外一个常用的type_traits是std::decay(朽化),它对于普通类型来说std::decay(朽化)是移除引用和cv符,大大简化了我们的书写。除了普通类型之外,std::decay还可以用于数组和函数,具体的转换规则是这样的:
?
  先移除T类型的引用,得到类型U,U定义为remove_reference::type。
?
如果is_array::value为 true,修改类型type为remove_extent::type *。
否则,如果is_function::value为 true,修改类型type将为add_pointer::type。
否则,修改类型type为 remove_cv::type。
std::decay的基本用法:
?
?
typedef std::decay::type A; ? ? ? ? ? // int
typedef std::decay::type B; ? ? ? ? ?// int
typedef std::decay::type C; ? ? ? ? // int
typedef std::decay::type D; ? ?// int
typedef std::decay::type E; ? ? ? ?// int*
typedef std::decay::type F; ? ? ?// int(*)(int)
?
  std::decay除了移除普通类型的cv符的作用之外,还可以将函数类型转换为函数指针类型,从而将函数指针变量保存起来,以便在后面延迟执行,比如下面的例子。
?
?
template
struct SimpFunction
{
? ? using FnType = typename std::decay::type;//先移除引用再添加指针
?
? ? SimpFunction(F& f) : m_fn(f){}
?
? ? void Run()
? ? {
? ? ? ? m_fn();
? ? }
?
? ? FnType m_fn;
};
?
  如果要保存输入的函数,则先要获取函数对应的函数指针类型,这时就可以用std::decay来获取函数指针类型了,using FnType = typename std::decay::type;实现函数指针类型的定义。type_traits还提供了获取可调用对象返回类型的元函数:std::result_of,它的基本用法:
?
?
int fn(int) {return int();} ? ? ? ? ? ? ? ? ? ? ? ? ? ?// function
typedef int(&fn_ref)(int); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // function reference
typedef int(*fn_ptr)(int); ? ? ? ? ? ? ? ? ? ? ? ? ? ? // function pointer
struct fn_class { int operator()(int i){return i;} }; ?// function-like class
?
int main() {
? typedef std::result_of::type A; ?// int
? typedef std::result_of::type B; ? ? ? ? // int
? typedef std::result_of::type C; ? ? ? ? // int
? typedef std::result_of::type D; ? ? ? // int
}
?
  type_traits还提供了一个很有用的元函数std::enable_if,它利用SFINAE(substitude failure is not an error)特性,根据条件选择重载函数的元函数std::enable_if,它的原型是:
?
template struct enable_if;
?
  根据enable_if的字面意思就可以知道,它使得函数在判断条件B仅仅为true时才有效,它的基本用法:
?
?
template
typename std::enable_if::value, T>::type foo(T t)
{
? ? return t;
}
auto r = foo(1); //返回整数1
auto r1 = foo(1.2); //返回浮点数1.2
auto r2 = foo(“test”); //compile error
?
  在上面的例子中对模板参数T做了限定,即只能是arithmetic(整型和浮点型)类型,如果为非arithmetic类型,则编译不通过,因为std::enable_if只对满足判断式条件的函数有效,对其他函数无效。
?
  可以通过enable_if来实现编译期的if-else逻辑,比如下面的例子通过enable_if和条件判断式来将入参分为两大类,从而满足所有的入参类型:
?
?
template
typename std::enable_if::value, int>::type foo1(T t)
{
? ? cout << t << endl;
? ? return 0;
}
?
template
typename std::enable_if::value, int>::type foo1(T &t)
{
? ? cout << typeid(T).name() << endl;
? ? return 1;
}
?
  对于arithmetic类型的入参则返回0,对于非arithmetic的类型则返回1,通过arithmetic将所有的入参类型分成了两大类进行处理。从上面的例子还可以看到,std::enable_if可以实现强大的重载机制,因为通常必须是参数不同才能重载,如果只有返回值不同是不能重载的,而在上面的例子中,返回类型相同的函数都可以重载。
?
  C++11的type_traits提供了近百个在编译期计算、查询、判断、转换和选择的元函数,为我们编写元程序提供了很大的便利。如果说C++11的type_traits让模版元编程变得简单,那么C++11提供的可变模板参数和tuple则进一步增强了模板元编程
?
4.可变模板参数
?
  C++11的可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数。关于它的用法和使用技巧读者可以参考笔者在程序员2015年2月A上的文章:泛化之美--C++11可变模版参数的妙用,这里不再赘述,这里将要展示的如何借助可变模板参数实现一些编译期算法,比如获取最大值、判断是否包含了某个类型、根据索引查找类型、获取类型的索引和遍历类型
首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇UVALive6814 Lexicography 下一篇UVA - 1616 Caravan Robbers 二分..

评论

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