(SFINAE)C++检查成员函数是否存在
来源:互联网 发布:英雄联盟mac有国服? 编辑:程序博客网 时间:2024/05/29 07:29
1.什么是SFINAE?
请看下面的链接 SFINAE
2.如果使用SFINAE检查类或者结构体是否定义某个成员函数?
这里直接给出代码,以operator()函数为例
#include <type_traits>#include <iostream>struct Hello{ void operator()() { std::cout << "Hello World" << std::endl; }};struct Generic {};#define HAS_MEM_FUNC(FunctionName, HelperClassName) \ template<typename T> \struct HelperClassName { \ typedef char one; \ typedef long two; \ template <typename C> static one test(decltype(&C::FunctionName)); \ template <typename C> static two test(...); \public: \enum { value = sizeof(test<T>(0)) == sizeof(char) }; \}HAS_MEM_FUNC(operator(), hasOperatorParentheses);template<class T, class Enable = void>class A{public: static const bool value = false; static void execute(const typename std::decay<T>::type & t){ std::cout << "no function to call" << std::endl; }};template<class T>class A <T, typename std::enable_if< hasOperatorParentheses<T>::value >::type >{public: static const bool value = true; static void execute(const typename std::decay<T>::type & t){ const_cast<typename std::decay<T>::type&>(t)(); }};int main(int argc, char *argv[]){ // Hello hello; //Generic gen; A<Hello>::execute(Hello()); A<Generic>::execute(Generic()); return 0;}
3.代码解释
#define HAS_MEM_FUNC(FunctionName, HelperClassName) \template<typename T> \struct HelperClassName { \typedef char one; \typedef long two; \template <typename C> static one test( decltype(&C::FunctionName)); \template <typename C> static two test( ...); \public: \enum { value = sizeof(test<T>(0)) == sizeof(char) }; \}这是第一次使用SFINAE的地方,编译器在选择模板时选择匹配最佳的来生成代码。
对于未知类型T,如果T存在符合条件的成员函数,则one test函数会被编译器选择,否则编译器会选择two test,没有其他更好选择的最后选择。
并且当编译器无法使用one test而选择two test时,并不会产生编译错误。
上述代码用宏包装了一下,这样可以方便代码再次利用,而不用copy paste。
template<class T, class Enable = void>class A {public:static const bool value = false;static void execute(const typename std::decay<T>::type & t){ std::cout<<"no function to call"<<std::endl;}};template<class T>class A <T, typename std::enable_if< hasOperatorParentheses<T>::value >::type > {public:static const bool value = true;static void execute(const typename std::decay<T>::type & t){ const_cast<typename std::decay<T>::type&>(t)();}};这是第二次使用SFINAE的地方,某些使用我们可以能会想写出如下代码(伪代码)
if(sometype has specified member function){ call member function}else{handle error}
但是我们不能这样做,因为编译器会做类型检查,即便那段代码不执行。所以假设sometype没有specfied member,if条件里面的代码无法编译。
引入A 模板的意义在于,使用类模板偏特化 和 enable if 进行代码的选择编译,这样保持了接口的统一,亦可产生不同行为。
这里使用std::decay是一个奇技淫巧,是为了函数接收左值也接收右值,并且不会发生copy。没有其他特别的用途,可以不使用。
0 0
- (SFINAE)C++检查成员函数是否存在
- c++ 检查是否存在成员函数
- linux c检查文件是否存在
- C语言 检查文件是否存在
- Linux C语言检查进程是否存在
- PHP下常见的检查函数(变量是否存在,文件是否存在 函数是否存在 方法是否存在)
- 检查文件是否存在
- 检查网页是否存在
- 检查进程是否存在
- 检查用户名是否存在
- 检查数据库是否存在
- 检查数据链是否存在
- 检查变量是否存在
- 检查目录是否存在
- delphi中检查URL是否存在的函数
- asp中检查某个文件夹是否存在函数
- 能实现检查窗口是否存在的函数
- 检查某个文件或目录是否存在的函数
- Android Universal Image Loader
- 基于DDD的.NET开发框架ABP实例,多租户 (Sass)应用程序,采用.NET MVC, Angularjs, EntityFramework-介绍
- spring mvc+spring+mybatis的配置
- nginx(1): linux下的安装
- 【Codeforces Gym】100162 H Temperature
- (SFINAE)C++检查成员函数是否存在
- [percona-toolkit]pt-query-digest用法
- 微信企业号注册教程 视频教程 公众号 服务号 订阅号
- 解析json串的两种方式
- Android混淆、逆向
- HIVE下分布式生成整型唯一ID
- RecycleView实现footer功能
- 777C Alyona and Spreadsheet
- 如何快速学习一门程序语言?