function_traits2 通过对函数特征的学习深入理解模板
通过对函数特征的学习深入理解模板
/*
* 函数特征
* 学习及改进自《深入应用C++11 代码优化与工程级应用》
*
* 符号概念:
* F - 函数概念(可调用对象)
* R - 返回值类型
* K - 类(class)类型
* Args... - 形参类型包
*/
#ifndef __FUNCTION_TRAITS_H__
#define __FUNCTION_TRAITS_H__
#include <functional>
#include <tuple>
#include <type_traits>
// 主模板
template <typename F>
struct function_traits;
// 普通函数特征
template<typename R, typename... Args>
struct function_traits<R(Args...)>
{
enum { arity = sizeof...(Args) };
using return_type = R;
using function_type = R(Args...);
using stl_function_type = std::function<function_type>;
using pointer = R(*)(Args...);
template<size_t I>
using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
template<size_t I>
struct args
{
static_assert(I < arity, "Index must less than sizeof Args.");
using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
};
};
// 函数指针特征
template<typename R, typename... Args>
struct function_traits<R(*)(Args...)> : function_traits<R(Args...)> {};
// std::function 特征
template<typename R, typename... Args>
struct function_traits<std::function<R(Args...)>> : function_traits<R(Args...)> {};
// 成员函数特征
#define KLASS_MEMBER_FUNCTION_TRAITS(...)\
template<typename R, typename K, typename... Args>\
struct function_traits<R(K::*)(Args...) __VA_ARGS__ > : function_traits<R(Args...)> {};
KLASS_MEMBER_FUNCTION_TRAITS()
KLASS_MEMBER_FUNCTION_TRAITS(const)
KLASS_MEMBER_FUNCTION_TRAITS(volatile)
KLASS_MEMBER_FUNCTION_TRAITS(const volatile)
#undef KLASS_MEMBER_FUNCTION_TRAITS
// std::bind 特征匹配
template <typename R, typename F, typename... Args>
struct function_traits<std::_Binder<R, F, Args...>> : function_traits<F> {};
// 仿函数特征
template<typename F>
struct function_traits : function_traits<decltype(&F::operator())> {};
// stl_function_type 别名
template <typename F>
using stl_function_type = typename function_traits<std::remove_reference_t<F>>::stl_function_type;
// 可调用对象(函数,函数指针,静态函数,仿函数,std::bind,std::function)转stl函数
template <typename F>
stl_function_type<F> to_function(F const& f)
{
return static_cast<stl_function_type<F>>(f);
}
template <typename F>
stl_function_type<F> to_function(F && f)
{
return static_cast<stl_function_type<F>>(std::forward<F>(f));
}
#endif
测试代码
#include <iostream>
#include "function_traits.hpp"
using namespace std;
static void test_function_traits();
template <typename T>
void print() { cout << typeid(T).name() << endl; }
template <typename F>
void print_function_traits(F && f)
{
using ft = function_traits<std::remove_reference_t<F>>;
cout << "RT " << typeid(ft::return_type).name() << endl;
cout << "FT " << typeid(ft::function_type).name() << endl;
cout << "SFT " << typeid(ft::stl_function_type).name() << endl;
cout << "PT " << typeid(ft::pointer).name() << endl;
cout << "AT(0) " << typeid(ft::type<0>).name() << endl;
cout << "AT(1) " << typeid(ft::type<1>).name() << endl;
}
int main()
{
test_function_traits();
return 0;
}
// 函数
void test01(int a, int b){
cout << __FUNCTION__ << endl;
}
//
struct Test02
{
// 静态函数
static void sf01(int a, int b) {
cout << __FUNCTION__ << endl;
}
// 仿函数
void operator()(int a, int b)
{
cout << __FUNCTION__ << endl;
}
// 成员函数
void mf01(int a, int b)
{
cout << __FUNCTION__ << endl;
}
};
static void test_function_traits()
{
auto tf1 = to_function(test01);
tf1(1,1);
tf1 = to_function(Test02::sf01);
tf1(1, 1);
tf1 = to_function(Test02());
tf1(1, 1);
Test02 tt;
tf1 = to_function([&tt](int a, int b) {cout << "----" << __FUNCTION__ << endl; tt.mf01(a, b); });
tf1(1, 1);
auto fb = std::bind(&Test02::mf01, tt, std::placeholders::_1, std::placeholders::_2);
tf1 = to_function(fb);
stl_function_type<decltype(tf1)> fr = fb;
cout << "--------------" << endl;
cout << typeid(fb).name() << endl;
cout << typeid(fr).name() << endl;
cout << "--------------" << endl;
tf1 = to_function(fr);
tf1(1, 1);
print_function_traits(tf1);
}