我如何制作一个用于定义函数typedef的C宏?

问题描述 投票:2回答:2

我想接受这个:

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);

...参数的数量是动态的,最后一个参数是返回类型。

如果无法将最后一个参数作为返回类型,则作为第二个参数。

c function pointers macros typedef
2个回答
2
投票

您想要的是variadic macro,它可以接受任意数量的参数。语法为#define MACRO(fixedarg1, fixedarg2, ...)。在宏的主体中,您只需使用__VA_ARGS__来引用所有变量参数。

不幸的是,您不能使最后一个arg成为返回类型,因为您必须统一对待整个可变参数块,并且它们必须排在最后。但是,您可以很容易地使第二个arg返回类型:

#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进行检查。


0
投票

如果您真的想要最后一个返回类型,那很复杂,但是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)部分放在一起。由于您的示例使用的是在宏之后提供分号,因此省略了最后的分号。

Example preprocessor output on coliru.

© www.soinside.com 2019 - 2024. All rights reserved.