以下源內容來自於《深入應用C++11 代碼優化與工程級應用》3.3.6 function_traits
/*
* function_traits用來獲取所有函數語義類型的信息,
* (函數類型、返回類型、參數個數和參數的具體類型)。
*
* 函數語義類型包括
* 普通函數
* 函數指針
* function/lambda
* 成員函數
* 函數對象
*
* 實現function_traits的關鍵技術
* 要通過模板特化和可變參數模板來獲取函數類型和返回類型。
* 先定義一個基本的function_traits的模板類:
* template<typename T>
* struct function_traits;
* 再通過特化,將返回類型和可變參數模板作為模板參數,就可以獲取函數類型、函數返回值和參數的個數了。
*
* 如:
* int func(int a, string b);
* ## 獲取函數類型
* function_traits<decltype(func)>::function_type; // int __cdecl(int, string)
* # 獲取函數返回值
* function_traits<decltype(func)>::return_type; // int
* # 獲取函數的參數個數
* function_traits<decltype(func)>::arity; // 2
* # 獲取函數第一個入參類型
* function_traits<decltype(func)>::args<0>::type; // int
* # 獲取函數第二個入參類型
* function_traits<decltype(func)>::args<1>::type; // string
*/
#ifndef __FUNCTION_TRAITS_H__
#define __FUNCTION_TRAITS_H__
#include <functional>
// 原型
template<typename T>
struct function_traits;
// 普通函數
template<typename ReturnType, typename... Args>
struct function_traits<ReturnType(Args...)>
{
enum { arity = sizeof...(Args) };
using return_type = ReturnType;
using function_type = ReturnType(Args...);
using stl_function_type = std::function<function_type>;
using pointer = ReturnType(*)(Args...);
template<size_t I>
struct args
{
static_assert(I < arity, "index is out of range, index must less than sizeof Args");
using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
};
using tuple_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
using bare_tuple_type = std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...>;
};
// 函數指針
template<typename ReturnType, typename... Args>
struct function_traits<ReturnType(*)(Args...)> : function_traits<ReturnType(Args...)> {};
// std::function
template<typename ReturnType, typename... Args>
struct function_traits<std::function<ReturnType(Args...)>> : function_traits<ReturnType(Args...)> {};
// 成員函數
#define FUNCTION_TRAITS(...)\
template <typename ReturnType, typename ClassType, typename... Args>\
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__> : function_traits<ReturnType(Args...)>{};\
FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)
// 函數對象
template<typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())> {};
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}
template<typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
{
return static_cast<typename function_traits<Function>::pointer>(lambda);
}
#endif
以下是測試代碼
#include <iostream>
#include <string>
#include "function_traits.hpp"
using namespace std;
int func(int a, string b);
template<typename T>
void printType()
{
cout << typeid(T).name() << endl;
}
float(*cast_func)(int, int, int, int);
float free_function(const string& a, int b)
{
return (float)a.size() / b;
}
struct AA
{
int f(int a, int b)volatile { return a + b; }
int operator()(int)const { return 0; }
};
void test_function_traits();
int main()
{
{
// 獲取函數類型
function_traits<decltype(func)>::function_type; // int __cdecl(int, string)
// 獲取函數返回值
function_traits<decltype(func)>::return_type; // int
// 獲取函數的參數個數
function_traits<decltype(func)>::arity; // 2
// 獲取函數第一個入參類型
function_traits<decltype(func)>::args<0>::type; // int
// 獲取函數第二個入參類型
function_traits<decltype(func)>::args<1>::type; // string
cout << typeid(function_traits<decltype(func)>::function_type).name() << endl;
cout << typeid(function_traits<decltype(func)>::return_type).name() << endl;
}
{
test_function_traits();
}
return 0;
}
void test_function_traits()
{
cout << "----------- 2 ----------" << endl;
std::function<int(int)> f = [](int a) {return a; };
printType<function_traits<std::function<int(int)>>::function_type>();
printType<function_traits<std::function<int(int)>>::args<0>::type>();
printType<function_traits<decltype(f)>::function_type>();
printType<function_traits<decltype(free_function)>::function_type>();
printType<function_traits<decltype(cast_func)>::function_type>();
printType<function_traits<AA>::function_type>();
using T = decltype(&AA::f);
printType<T>();
printType<function_traits<decltype(&AA::f)>::function_type>();
static_assert(std::is_same<function_traits<decltype(f)>::return_type, int>::value, "");
}
int func(int a, string b)
{
return 0;
}