杂货边角(13):利用可变参数模板根据函数指针得到返回值类型和形参类型
2018-02-01 22:39
246 查看
前面提到过variadic template机制最为核心的便是“递归”思想,这里通过一个比较生僻的使用案例来阐述可变参数模板,以及decltype和declval的使用示例。
当然,现在还有一个问题,就是只能列出形参列表的第一项,后续的形参类型的获取要么再专门在模板类中设置更多的域,但是显然代码不够动态性。可想要使用递归的方式获取,却始终没能实现,将这个问题暂且留在这里,后面找到方法再来更新。
#include <iostream> #include <sstream> #include <type_traits> #include <typeinfo> using namespace std; class A{}; template<typename T> std::ostream& print (std::ostream& os, T param) { return os<< typeid(param).name() << ".."<<endl; } template<typename T, typename... Args> std::ostream& print (std::ostream& os, T param, Args... rest) { os<< typeid(param).name() << ", "; return print(os, rest...); } template< typename T, typename... U> //模板元结构体的声明惯例,else error: GetParam1Type is not a class template class GetParam1Type; template< typename T, typename U, typename... V> class GetParam1Type< T(U, V...) > { public: typedef U Result; }; template< typename T > class GetParam1Type< T(void) > { public: typedef void Result; }; template< typename T, typename U, typename... V> class GetParam1Type< T(*)(U, V...) > { public: typedef U Result; }; template< typename T > class GetParam1Type< T(*)( void )> { public: typedef void Result; }; template< typename T, typename U, typename V, typename... R > class GetParam1Type< T (V::*)(U, R...) > { public: typedef U Result; }; template< typename T, typename V > class GetParam1Type< T (V::*)( void )> { public: typedef void Result; }; typedef void (A::*fun1 )(int, long, double ); typedef void (A::*fun2 )( ); typedef long fun3( float, long, double ); typedef int fun4( ); typedef long (*fun5)(int, int, int); typedef long (*fun6)( ); /*********************************************************************************** /*介绍函数: result_of /*功能: 根据已有函数(函数调用实例或引用)推导该函数返回值类型 /*原理:在<type_traits>库中,result_of结构模板类是基于decltype和declval实现的 /*可以参考的链接:https://stackoverflow.com/questions/11470802/stdresult-of-simple-function template<class> struct result_of; template<class F, class... ArgTypes> struct result_of<F(ArgTypes...)> (C++17中弃用了,改用invoke_result) { typedef decltype( std::declval<F>()(std::declval<ArgTypes>()...) ) type; }; /*调用示例: result_of< func(1,2.4) >::type f; /***********************************************************************************/ /*******改进一下,提供可以根据函数指针获得返回值类型调用方式*********************/ template<class> struct modified_result_of; template<typename ReturnType, typename... ParamTypes> struct modified_result_of< ReturnType (*)(ParamTypes...) > { typedef ReturnType type; }; int main() { /*获取函数指针指向的函数的返回值类型*/ result_of< fun5(int,int,int) >::type return_value; //result_of<>特化要求的是typename,而不是具体实例,所以result_of<fun5(1,1,1)>是不行的 cout << typeid(return_value).name() << endl; //l //typeid是返回变量对应的typeinfo数据结构,typeinfo含有name和hash_code两域 modified_result_of<fun6>::type temp; cout << typeid(temp).name() << endl; //l /*可变参数模板的使用经典案例*/ print(std::cout, 12, 12.3, 12); //i, d, i.. decltype(declval<int>()) now_val = 10; //declval是根据变量类型返回一个匿名对象的右值引用,故而这里必须要初始化 cout << typeid(now_val).name() << endl;//i GetParam1Type<fun1>::Result f1; //fun1是函数指针 cout << "function ptr fun1 first param type is: "<< typeid(f1).name() << endl; //i GetParam1Type<fun3>::Result f3; //fun3是函数对象 cout << "function ptr fun3 first param type is: "<< typeid(f3).name() << endl; //f /*获取函数指针指向的函数的第一个形参类型*/ /* if (is_same< GetParam1Type<fun1>::Result, void>::value == 1) { cout << "function ptr fun1 first param type is: "<<" void" <<endl; } else{ GetParam1Type<fun1>::Result f1; cout << "function ptr fun1 first param type is: "<< typeid(f1).name() << endl; } cout<<is_same< GetParam1Type<fun2>::Result, void>::value<<endl; */ return 0; }
当然,现在还有一个问题,就是只能列出形参列表的第一项,后续的形参类型的获取要么再专门在模板类中设置更多的域,但是显然代码不够动态性。可想要使用递归的方式获取,却始终没能实现,将这个问题暂且留在这里,后面找到方法再来更新。
相关文章推荐
- 函数指针(函数指针作为函数形参/函数类型作为函数返回类型)
- C++利用二级指针做函数形参来进行修改实参的实例分析
- 根据数据库字段类型返回c#类型函数
- 对引用和指针使用以及函数返回引用和指针类型的理解
- 【C++总结】函数形参,返回const对象与非const对象,成员函数,函数指针
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
- 常成员函数返回指针的类型
- 函数返回类型为指针类型时的一些问题
- 如果从函数中返回局部变量的地址,引用或者指针的形式,则变量类型必须是静态的或者常量,即不在栈中存储
- 函数返回const引用形参的指针问题
- 为什么函数不能根据返回类型来区分重载?
- 函数返回类型为指针的时候的注意事项
- 函数操作符:返回类型 operator()(形参表)const
- 利用返回指针值的函数进行查找学生的成绩
- 对引用和指针使用以及函数返回引用和指针类型的理解
- 关于函数返回值为指针类型的分析
- 定义struct/struct定义在哪里/函数返回指针类型/指针数组与数组指针/{}里是局部定义/fabs、abs
- 自定义函数中返回值为指针类型的问题(2)
- 函数返回的如果是指针类型则使用自动释放池:
- 函数返回类型为指针类型的一些问题