[C++技巧篇1]enable_if,lambda
2017-10-17 01:16
267 查看
麦片说
各位C++的用户,是否已经开始用C++11了呢?至少也是体验过boost的吧?本文不是关于如何用的,而是总结一些小技巧。这些小技巧嘛,小麦第一次看到的时候的感受通常是。。。”我擦嘞,还能这样!!这不科学吧?!“,经过尝试,小麦发现,这。。。真的是科学的!
这个东西出现在C++11和boost中,两者用法略有区别,本文就以C++11中的std::enable_if为例,说说这个诡异的存在。大概说来,这个东西的实现是非常简单,甚至看上去略微幼稚的
这个东西最大的作用在于提供一些针对性的重载,当然,这需要配合一些类型判断之类的,这个技巧相信大家是能接受的,这里只说一个技巧,那就是返回值不同的重载。大家知道,重载必须是参数不同,只有返回值不同,这是不行的!但是,C++是个好语言,只要主人高兴,穿着黑丝被推倒也没关系的。。。于是,就有了这样的用法:
这确实是重载呢,客官且看下面的例子
这两次foo调用的分别是两个不同的东西,而且,这两个东西的参数是一样的,只是返回值不一样,类似的技巧和lambda配合更是天衣无缝啊!
此等神器的出现,直接使小麦抛弃了boost和C++11中的bind,那传参,那自由,那类型推导,真是完虐bind之流啊。不知道基本用法的同志请翻手册,此文不是入门手册。下面只说一个技巧,就是小麦最喜欢的用法
当然,上例是错误的,因为auto并不能让编译器推断出对应的类型,并且,如果是void的话,这里还不能return!当然,这是难不倒小麦的,我说过,C++是个好姑娘(语言)!首先,我们要能推断出返回值类型,这并不复杂,复杂的小麦也搞不定啊!
有了返回类型,就好办多了,下面又是enable_if出场的时间了,
就是这样,通过配合is_void判断返回类型是否为void,加上enable_if,就解决了lambda的返回值问题,实现了相同参数的重载。由于C++的故事比较丰富,所以。。。小麦下次再写吧!
下期预告:boost::function与boost::asio::yield,同样奇葩,敬请期待!
各位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,同样奇葩,敬请期待!
相关文章推荐
- C++ std::enable_if解析
- c++ 11 enable_if
- C/C++ 中的宏 (#define) 与预处理 (#if/#ifdef/#pragma) 的使用方法大全、使用技巧
- C++学习 boost学习之-enable_if
- C++几个技巧:智能指针在消息传递中的使用,元组,及lambda删除器
- C++几个技巧:智能指针在消息传递中的使用,元组,及lambda删除器
- C++编程技巧
- c++语法补充+oj技巧讲解
- 以水仙花数论C++中while和if的区别
- 【C++学习】函数对象和Lambda表达式
- C++技巧之operator操作符
- c&c++内存调试技巧
- C++文件读写详解(ofstream,ifstream,fstream)
- c++平台国际化前期工作技巧
- 遇见C++ Lambda
- C++教程之lambda表达式
- C/C++ struct初始化/复制/内存分配技巧
- C中如何调用C++函数的技巧(转)
- C++技术技巧之一
- C++技巧之operator操作符