[C++技巧篇1]enable_if,lambda


各位C++的用户,是否已经开始用C++11了呢?至少也是体验过boost的吧?本文不是关于如何用的,而是总结一些小技巧。这些小技巧嘛,小麦第一次看到的时候的感受通常是。。。”我擦嘞,还能这样!!这不科学吧?!“,经过尝试,小麦发现,这。。。真的是科学的!

enable_if

http://ju.outofmemory.cn/entry/30164

这个东西出现在C++11和boost中,两者用法略有区别,本文就以C++11中的std::enable_if为例,说说这个诡异的存在。大概说来,这个东西的实现是非常简单,甚至看上去略微幼稚的

template<bool, typename _Tp = void>
	struct enable_if { };	
	template<typename _Tp>
	struct enable_if<true, _Tp>{ typedef _Tp type; };

这个东西最大的作用在于提供一些针对性的重载,当然,这需要配合一些类型判断之类的,这个技巧相信大家是能接受的,这里只说一个技巧,那就是返回值不同的重载。大家知道,重载必须是参数不同,只有返回值不同,这是不行的!但是,C++是个好语言,只要主人高兴,穿着黑丝被推倒也没关系的。。。于是,就有了这样的用法:

template <class T>
	typename std::enable_if<std::is_arithmetic<T>::value, int>::type foo( T &t)
	{
		return static_cast<int>(t);
	}
	template <class T>
	typename std::enable_if<std::is_class<T>::value, T>::type & foo( T &t)
	{
		return t;
	}

这确实是重载呢,客官且看下面的例子

foo(n1);
Myclass a;
foo(a);

这两次foo调用的分别是两个不同的东西,而且,这两个东西的参数是一样的,只是返回值不一样,类似的技巧和lambda配合更是天衣无缝啊!

lambda

此等神器的出现,直接使小麦抛弃了boost和C++11中的bind,那传参,那自由,那类型推导,真是完虐bind之流啊。不知道基本用法的同志请翻手册,此文不是入门手册。下面只说一个技巧,就是小麦最喜欢的用法

template <class FT>
	auto 	call(FT && f){return f();} //This is a wrong case
	
	call([](){std::cout<<"do anything you want"<<std::endl;});

当然,上例是错误的,因为auto并不能让编译器推断出对应的类型,并且,如果是void的话,这里还不能return!当然,这是难不倒小麦的,我说过,C++是个好姑娘(语言)!首先,我们要能推断出返回值类型,这并不复杂,复杂的小麦也搞不定啊!

template<class F>
	struct deduce_function{};
	
	template<class Ret, class C, class... Args>
	struct deduce_function<Ret (C::*)(Args...) const>
	{
	    typedef std::function<Ret (Args...)> type;
	    typedef Ret ret_type;
	};
	
	template<class Ret, class C, class... Args> 
	struct deduce_function<Ret (C::*)(Args...)> 
	{ 
	   typedef std::function<Ret(Args...)> type; 
	   typedef Ret		ret_type;
	};
	
	template<class F>
	struct function_res_traits
	{
		typedef typename 	deduce_function<decltype(&std::remove_reference<F>::type::operator())>::ret_type ret_type;
	};

有了返回类型,就好办多了,下面又是enable_if出场的时间了,

template<class FT>
	auto  call(FT && f)
	-> typename std::enable_if<std::is_void<typename function_res_traits<FT>::ret_type>::value, void>::type
	{
		f();
	}
	
	template<class FT>
	auto  call(FT && f )
	-> typename std::remove_reference<typename function_res_traits<FT>::ret_type>::type &&
	{
		 return f();
	}

就是这样,通过配合is_void判断返回类型是否为void,加上enable_if,就解决了lambda的返回值问题,实现了相同参数的重载。由于C++的故事比较丰富,所以。。。小麦下次再写吧!

下期预告:boost::function与boost::asio::yield,同样奇葩,敬请期待!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值