C++组件扩展实现:函数特性function_traits

#include<functional>
#include<tuple>
#include<type_traits>
#include<iostream>
using namespace std;

template<typename T>
struct function_traits;

//处理普通函数
template<typename RET,typename ...ARGS>
struct function_traits<RET(ARGS...)>
{
	constexpr static size_t arity = sizeof...(ARGS);

	using function_type = RET(ARGS...);
	using Ret_type = RET;

	using stl_functional_type = std::function<function_type>;
	using function_pointer = RET(*)(ARGS...);

	template<size_t I>
	struct ArgN
	{
		static_assert(I < arity, "failed!");
		using type = std::tuple_element_t<I, std::tuple<ARGS...>>;
	};
	template<size_t I>
	using ArgN_t = typename ArgN<I>::type;
};



//处理函数指针
template<typename RET, typename ...ARGS>
struct function_traits<RET(*)(ARGS...)> :function_traits<RET(ARGS...)> {
	using function_type = RET(*)(ARGS...);
};
//处理std::function
template<typename RET, typename ...ARGS>
struct function_traits<std::function<RET(ARGS...)>> :function_traits<RET(ARGS...)> {
	using function_type = std::function<RET(ARGS...)>;
};

/*
【使用可变参数宏实现,可变参数宏的列表...与宏定义中的__VA_ARGS__ 对应替换;而非与宏定义中的...对应替换】

可变参数为空:
假如定义了如下宏(不管是使用标准 C 方式还是 GNU C方式都可以,这里使用标准 C 的方式):
#define eprintf(format, ...) fprintf (stderr, format, __VA_ARGS__)
在标准 C 的环境下进行如下调用,可变参数为空:
eprintf("success!\n");
宏的扩展将会报错,因为扩展出来后的形式如下:

fprintf(stderr, "success!\n",);
fprintf 最后一个参数后面多了一个逗号,这样将报错。这种情况在标准 C 下无法解决,但是 GNU C可以解决。GNU C 赋予 "##" 另一种特殊意义(不是字符串连接的意义了),如果在可变参数前面加上"##",当可变参数为空时,前面的逗号会被删除:

#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
// 或者
#define eprintf(format, args...) fprintf(stderr, format, ##args)
当可变参数为空时,宏都会扩展成:
fprintf(stderr, "success!\n");
可以看到最后一个参数后面的逗号被删除了。
Clang 默认使用 GNU11,因此也支持这个功能。
*/

//处理成员函数
#define FUNCTION_TRAITS(...)															    \
template<typename RET, typename Class,typename ...ARGS>										\
struct function_traits<RET(Class::*)(ARGS...)__VA_ARGS__> :function_traits<RET(ARGS...)> {	\
	using function_type = RET(Class::*)(ARGS...)__VA_ARGS__;								\
protected:																					\
	using logic_function_type= RET(ARGS...);									            \
};

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

//处理函数对象
template<typename Callable>
struct function_traits :function_traits<decltype(&Callable::operator())> {
	using function_type =typename function_traits<Callable>::logic_function_type;//函数对象模拟成普通函数的类型
};


template<typename T>
void Print_Type()
{
	std::cout << typeid(T).name() << std::endl;
}

int Print(int, double) { return 0; }

//函数对象
struct MyStruct
{
	double Fn(char, char) const { return 0; }
	char operator()(double, char*) {
		return ' ';
	}
};

int main()
{
	auto fn = std::function<int(int, double)>(Print);
	Print_Type<function_traits<decltype(fn)>::function_type>();
	constexpr auto nargs = function_traits<decltype(Print)>::arity;
	Print_Type<function_traits<decltype(Print)>::function_type>();
	Print_Type<function_traits<decltype(&Print)>::function_type>();
	Print_Type<function_traits<MyStruct>::function_type>();
	Print_Type<function_traits<decltype(&MyStruct::Fn)>::function_type>();

	using T = decltype(&MyStruct::Fn);
	Print_Type<T>();
	Print_Type<function_traits<decltype(Print)>::Ret_type>();
	Print_Type<function_traits<decltype(Print)>::function_pointer>();
	Print_Type<function_traits<decltype(Print)>::ArgN_t<1>>();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值