您的位置:首页 > 编程语言 > C语言/C++

杂货边角(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;
}


当然,现在还有一个问题,就是只能列出形参列表的第一项,后续的形参类型的获取要么再专门在模板类中设置更多的域,但是显然代码不够动态性。可想要使用递归的方式获取,却始终没能实现,将这个问题暂且留在这里,后面找到方法再来更新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐