function_traits通過模板特化和可變參數模板來獲取函數類型和返回類型


以下源內容來自於《深入應用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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM