【C++】More C++ 模板推导

进入C++11时代,大部分流行的库都支持了C++11的新特性。C++11的新特性虽然有时候被诟病为语法糖,但是确实对开发很有助力,甚至有时候跟脚本语言的简洁度有的一拼了。其中自动模板推导是C++11的惊艳功能之一,如果仅仅知道auto和decltype是不够的。以下笔记均以vs2013为准。
首先auto功能已经广为人知,auto可以根据当前表达式自动推导出当前变量的类型。auto推导一般是不带有引用&的,所以最好手动加&,即auto &;auto倾向于不带有const,只有必要情况下才带有const,比如容器是const引用,不用const迭代器不行。如下是不行的:

auto i; i=10;

这说明auto不能根据无关的上下文来推导。函数返回值可以用auto,比如:

auto foo(int i, int j)->decltype(i + j)
{
    return i + j;
}
auto f = [](int i, int j){return i + j; };

C++11的具名函数返回值判定需要->decltype语句,这使得函数非常难写难看,限制了使用范围;匿名函数却不需要。目前C++14可以不用写后面的->decltype,真正好用,不过普及还要一段时间。
decltype能获取已有变量模板。decltype是C++关键词,不是由其他模块组成的。如果使用旧版C++,可以使用boost库的typeof宏来自动推断类型。decltype的推断类型有一些问题,比如左值引用的数据,其模板推导带有引用&的,比如有如下代码,仅仅作为演示:

std::vector<int> vec = {1,2,3};
decltype<vec[0]> a = 10;//error!!
decltype<vec[0]> b;//error!!

编译器会报错,提示a,b都是左值引用。我只是想获取vector的模板,不需要引用啊?这时候有两种做法:
1、使用value_type,即

decltype(vec)::value_type a=10;

vetor的内部实现使用了type_traits技术,获取模板类型非常简单。
2、去引用:

typedef  std::remove_reference<decltype(annotationList_)::reference>::type a = 10;
typedef  std::remove_reference<decltype(annotationList_[0])>::type a = 10;

第一种方法使用vector内部type_traits技术提供的模板引用。两种方法使用了去引用功能,其内部实现很简单,因为模板匹配会把const、&、*分离出来:

template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };

按照这个想法,去除const和指针都是非常简单的事情,仅展示部分:

template<typename T> struct remove_pointer<T*> { typedef T type; };
template <class T> struct remove_const<const T> { typedef T type; };
template <class T> struct remove_const<const T[]> { typedef T type[]; };
template<typename T> struct remove_all { typedef T type; };
template<typename T> struct remove_all<T const&>  { typedef typename remove_all<T>::type type; };

同理还有添加的功能:

template<typename T> 
struct add_const_on_value_type{typedef const T type;};
template<class _Ty>
struct add_rvalue_reference{typedef _Ty&& type;};

但是不要想着这么高端就把添加const/&/*的功能也照上述方法写一遍,其实直接在推导好的纯净模板上面添加const/&/*就行了。

在实现上述功能的文件里面,还有一些有意思的模板编程方法:

  • 比较两个变量模板是否相同需要定义两个模板函数,根据模板匹配来执行
template<typename T, typename U> struct is_same { enum { value = 0 }; };
template<typename T> struct is_same<T,T> { enum { value = 1 }; };
  • 模板是否带有const:
template <typename T> struct is_const { enum { value = 0 }; };
template <typename T> struct is_const<T const> { enum { value = 1 }; 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值