杂货边角(13):利用可变参数模板根据函数指针得到返回值类型和形参类型

前面提到过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;
}

当然,现在还有一个问题,就是只能列出形参列表的第一项,后续的形参类型的获取要么再专门在模板类中设置更多的域,但是显然代码不够动态性。可想要使用递归的方式获取,却始终没能实现,将这个问题暂且留在这里,后面找到方法再来更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值