如何制作用于定义函数 typedef 的 C 宏?
How can I make a C macro for defining function typedefs?
我要拍这个:
typedef int (*PTR_FUN)(int);
typedef int (*PTR_FUN_FUN)(PTR_FUN, PTR_FUN);
并这样定义它:
MAKE_FUNCTION_TYPE(PTR_FUN, int, int);
MAKE_FUNCTION_TYPE(PTR_FUN_FUN, PTR_FUN, PTR_FUN, int);
...其中参数数量是动态的,最后一个参数是 return 类型。
如果无法将最后一个参数作为 return 类型,则作为第二个参数。
你想要的是一个可变参数宏,它可以接受任意数量的参数。语法是 #define MACRO(fixedarg1, fixedarg2, ...)
。在宏的主体中,您只需使用 __VA_ARGS__
来引用所有可变参数。
不幸的是,您不能将最后一个参数设置为 return 类型,因为您必须统一对待整个可变参数块并且它们必须排在最后。但是,您可以非常轻松地将第二个参数设为 return 类型:
#define MAKE_FUNCTION_TYPE(name, ret, ...) typedef ret (*name)(__VA_ARGS__)
MAKE_FUNCTION_TYPE(v_i, int);
MAKE_FUNCTION_TYPE(i_v, void, int);
MAKE_FUNCTION_TYPE(ii_cp, char *, int, int);
这相当于
typedef int (*v_i)();
typedef void (*i_v)(int);
typedef char * (*ii_cp)(int, int);
您可以使用 cc -E
.
检查
如果你真的想要最后的 return 类型,那很复杂,但是 Boost.Preprocessor(它适用于 C 和 C++)可以帮助做到这一点:
#include <boost/preprocessor/tuple.hpp>
#include <boost/preprocessor/variadic.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/greater.hpp>
#define PP_VARIADIC_BACK(...) \
BOOST_PP_TUPLE_ELEM(BOOST_PP_DEC(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
#define PP_VARIADIC_POP_BACK(...) \
BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1), \
BOOST_PP_TUPLE_POP_BACK(BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)), \
(void))
#define MAKE_FUNCTION_TYPE(name, ...) \
typedef PP_VARIADIC_BACK(__VA_ARGS__) (*name) PP_VARIADIC_POP_BACK(__VA_ARGS__)
辅助宏 PP_VARIADIC_BACK
需要至少一个参数并生成最后一个参数。辅助宏 PP_VARIADIC_POP_BACK
需要至少一个参数。当它获得多个参数时,它会在括号中包含除最后一个参数之外的所有参数的逗号分隔列表。当它恰好得到一个参数时,它会生成文本 (void)
.
然后可以将它们与 typedef
和 (*name)
部分放在一起。最后一个分号被省略了,因为您的示例在宏之后使用了一个分号。
我要拍这个:
typedef int (*PTR_FUN)(int);
typedef int (*PTR_FUN_FUN)(PTR_FUN, PTR_FUN);
并这样定义它:
MAKE_FUNCTION_TYPE(PTR_FUN, int, int);
MAKE_FUNCTION_TYPE(PTR_FUN_FUN, PTR_FUN, PTR_FUN, int);
...其中参数数量是动态的,最后一个参数是 return 类型。
如果无法将最后一个参数作为 return 类型,则作为第二个参数。
你想要的是一个可变参数宏,它可以接受任意数量的参数。语法是 #define MACRO(fixedarg1, fixedarg2, ...)
。在宏的主体中,您只需使用 __VA_ARGS__
来引用所有可变参数。
不幸的是,您不能将最后一个参数设置为 return 类型,因为您必须统一对待整个可变参数块并且它们必须排在最后。但是,您可以非常轻松地将第二个参数设为 return 类型:
#define MAKE_FUNCTION_TYPE(name, ret, ...) typedef ret (*name)(__VA_ARGS__)
MAKE_FUNCTION_TYPE(v_i, int);
MAKE_FUNCTION_TYPE(i_v, void, int);
MAKE_FUNCTION_TYPE(ii_cp, char *, int, int);
这相当于
typedef int (*v_i)();
typedef void (*i_v)(int);
typedef char * (*ii_cp)(int, int);
您可以使用 cc -E
.
如果你真的想要最后的 return 类型,那很复杂,但是 Boost.Preprocessor(它适用于 C 和 C++)可以帮助做到这一点:
#include <boost/preprocessor/tuple.hpp>
#include <boost/preprocessor/variadic.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/greater.hpp>
#define PP_VARIADIC_BACK(...) \
BOOST_PP_TUPLE_ELEM(BOOST_PP_DEC(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__))
#define PP_VARIADIC_POP_BACK(...) \
BOOST_PP_IF(BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1), \
BOOST_PP_TUPLE_POP_BACK(BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)), \
(void))
#define MAKE_FUNCTION_TYPE(name, ...) \
typedef PP_VARIADIC_BACK(__VA_ARGS__) (*name) PP_VARIADIC_POP_BACK(__VA_ARGS__)
辅助宏 PP_VARIADIC_BACK
需要至少一个参数并生成最后一个参数。辅助宏 PP_VARIADIC_POP_BACK
需要至少一个参数。当它获得多个参数时,它会在括号中包含除最后一个参数之外的所有参数的逗号分隔列表。当它恰好得到一个参数时,它会生成文本 (void)
.
然后可以将它们与 typedef
和 (*name)
部分放在一起。最后一个分号被省略了,因为您的示例在宏之后使用了一个分号。