C++ 如何通过之前编写的预处理器定义获取函数签名?

C++ 如何通过之前编写的预处理器定义获取函数签名?,c++,boost,boost-preprocessor,C++,Boost,Boost Preprocessor,我想创建一个define来解析函数签名,并使用Boost预处理器创建如下内容: MY_DEFINE std::string fun(int t, float b) { 或者至少: MY_DEFINE(std::string)(fun)(int t, float b) { 这将产生: class fun_in { int t; float b; } class fun_out { std::string value; } void my_fun_wrapper(in

我想创建一个define来解析函数签名,并使用Boost预处理器创建如下内容:

MY_DEFINE std::string fun(int t, float b)
{
或者至少:

MY_DEFINE(std::string)(fun)(int t, float b)
{
这将产生:

class fun_in
{
    int t;
    float b;
}

class fun_out
{
    std::string value;
}

void my_fun_wrapper(int t, float b)
{
}

std::string fun(int t, float b)
{
    my_fun_wrapper(t, b);
对于具有该定义的每个函数


是否可以通过Boost预处理器为
N
传入参数和任何返回类型的函数创建这样的定义包装器?

好吧,预处理器不能在不预先通知的情况下解析令牌。因此,您需要使用更多的括号。下面是它的外观:

DEFINE( (std::string)(fun)((int) a, (float) b) )
{
    return "Hello World!";
}
下面介绍如何使用boost创建宏(我假设您熟悉它的预处理器库)。首先是定义一些宏来处理括号,因为boost根本不处理带有逗号的序列:

#define REM(...) __VA_ARGS__
#define EAT(...)

// Retrieve the type
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__)
#define DETAIL_TYPEOF_HEAD(x, ...) REM x
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
// Strip off the type
#define STRIP(x) EAT x
// Show the type without parenthesis
#define PAIR(x) REM x
接下来,您需要以三种不同的方式处理args。首先,将它们作为成员变量输出(如
inta;float b;
)。然后作为函数参数(如
(int a,float b)
)。最后作为前向参数传递给另一个函数(如
(a,b)

接下来,我们创建一个包含三个参数的
DETAIL\u DEFINE
宏。首先是函数名、参数,然后是返回值。这将生成您想要的类和函数:

#define DETAIL_DEFINE(name, args, ...) \
struct BOOST_PP_CAT(name, _in) \
{ \
    DETAIL_DEFINE_MEMBERS(args) \
}; \
struct BOOST_PP_CAT(name, _out) \
{ \
    __VA_ARGS__ value; \
}; \
__VA_ARGS__ BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_ARGS(args) ; \
__VA_ARGS__ name DETAIL_DEFINE_ARGS(args) \
{ \
    return BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_FORWARD(args); \
} \
__VA_ARGS__ BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_ARGS(args)
最后,
DEFINE
宏将解析出所有括号,并将它们传递给
DETAIL\u DEFINE
宏:

#define DEFINE(x) DETAIL_DEFINE(TYPEOF(STRIP(x)), (TYPEOF(STRIP(STRIP(x)))), TYPEOF(x))
所以现在当你写作时:

DEFINE( (std::string)(fun)((int) a, (float) b) )
{
    return "Hello World!";
}
它应该输出:

struct fun_in
{
    int a;
    float b;
};
struct fun_out
{
    std::string value;
};
std::string fun_impl(int a, float b);
std::string fun(int a, float b)
{
    return fun_impl(a, b);
}
std::string fun_impl(int a, float b)
{
    return "Hello World!";
}

请注意,这在MSVC中不起作用,但有一些变通方法。此外,您还需要使用
-DBOOST\u PP\u VARIADICS=1
进行编译。好的,预处理器不能在不预先通知的情况下解析令牌。因此,您需要使用更多的括号。下面是它的外观:

DEFINE( (std::string)(fun)((int) a, (float) b) )
{
    return "Hello World!";
}
下面介绍如何使用boost创建宏(我假设您熟悉它的预处理器库)。首先是定义一些宏来处理括号,因为boost根本不处理带有逗号的序列:

#define REM(...) __VA_ARGS__
#define EAT(...)

// Retrieve the type
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__)
#define DETAIL_TYPEOF_HEAD(x, ...) REM x
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
// Strip off the type
#define STRIP(x) EAT x
// Show the type without parenthesis
#define PAIR(x) REM x
接下来,您需要以三种不同的方式处理args。首先,将它们作为成员变量输出(如
inta;float b;
)。然后作为函数参数(如
(int a,float b)
)。最后作为前向参数传递给另一个函数(如
(a,b)

接下来,我们创建一个包含三个参数的
DETAIL\u DEFINE
宏。首先是函数名、参数,然后是返回值。这将生成您想要的类和函数:

#define DETAIL_DEFINE(name, args, ...) \
struct BOOST_PP_CAT(name, _in) \
{ \
    DETAIL_DEFINE_MEMBERS(args) \
}; \
struct BOOST_PP_CAT(name, _out) \
{ \
    __VA_ARGS__ value; \
}; \
__VA_ARGS__ BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_ARGS(args) ; \
__VA_ARGS__ name DETAIL_DEFINE_ARGS(args) \
{ \
    return BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_FORWARD(args); \
} \
__VA_ARGS__ BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_ARGS(args)
最后,
DEFINE
宏将解析出所有括号,并将它们传递给
DETAIL\u DEFINE
宏:

#define DEFINE(x) DETAIL_DEFINE(TYPEOF(STRIP(x)), (TYPEOF(STRIP(STRIP(x)))), TYPEOF(x))
所以现在当你写作时:

DEFINE( (std::string)(fun)((int) a, (float) b) )
{
    return "Hello World!";
}
它应该输出:

struct fun_in
{
    int a;
    float b;
};
struct fun_out
{
    std::string value;
};
std::string fun_impl(int a, float b);
std::string fun(int a, float b)
{
    return fun_impl(a, b);
}
std::string fun_impl(int a, float b)
{
    return "Hello World!";
}

请注意,这在MSVC中不起作用,但有一些变通方法。此外,还需要使用
-DBOOST\u PP\u VARIADICS=1

编译此宏中最后一个逗号的用途是什么

#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
我认为它的结尾有一个额外的逗号,可以编码为

#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x)
检查此宏中没有最后一个逗号时它将如何工作

1.)详细定义的第一个参数

STRIP( (std::string)(fun)((int) a, (float) b) ) --> (fun)((int) a, (float) b)

TYPEOF( (fun)((int)a, (float) b)) ) -->  fun
STRIP( STRIP( (std::string)(fun)((int)a, (float) b) ) ) --> ( ( int ) a , ( float ) b )

TYPEOF ( ( ( int ) a , ( float ) b ) ) --> ( int ) a , ( float ) b
TYPEOF ( (std::string )( fun )(( int ) a , ( float ) b) ) --> std::string
2.)详细定义的第二个参数

STRIP( (std::string)(fun)((int) a, (float) b) ) --> (fun)((int) a, (float) b)

TYPEOF( (fun)((int)a, (float) b)) ) -->  fun
STRIP( STRIP( (std::string)(fun)((int)a, (float) b) ) ) --> ( ( int ) a , ( float ) b )

TYPEOF ( ( ( int ) a , ( float ) b ) ) --> ( int ) a , ( float ) b
TYPEOF ( (std::string )( fun )(( int ) a , ( float ) b) ) --> std::string
3.)详细定义的第三个参数

STRIP( (std::string)(fun)((int) a, (float) b) ) --> (fun)((int) a, (float) b)

TYPEOF( (fun)((int)a, (float) b)) ) -->  fun
STRIP( STRIP( (std::string)(fun)((int)a, (float) b) ) ) --> ( ( int ) a , ( float ) b )

TYPEOF ( ( ( int ) a , ( float ) b ) ) --> ( int ) a , ( float ) b
TYPEOF ( (std::string )( fun )(( int ) a , ( float ) b) ) --> std::string
结果:

DETAIL_DEFINE ( fun , (( int ) a , ( float ) b), std::string )
顺便说一句,对于那些没有boost\u PP\u VARIADIC\u TO_SEQ的旧boost的用户,请使用 如下所示:

#define BOOST_PP_VARIADIC_TO_SEQ(...) BOOST_PP_TUPLE_TO_SEQ(PP_NARG(__VA_ARGS__) , (__VA_ARGS__))
通过谷歌搜索,你可以在任何地方找到PP_NARG,这是:

//Original Author: Unknown, but well recognized recursive variadic macro
#define PP_NARG(...)        PP_NARG_IMPL(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_IMPL(...)   PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0

此宏中最后一个逗号的用途是什么

#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
我认为它的结尾有一个额外的逗号,可以编码为

#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x)
检查此宏中没有最后一个逗号时它将如何工作

1.)详细定义的第一个参数

STRIP( (std::string)(fun)((int) a, (float) b) ) --> (fun)((int) a, (float) b)

TYPEOF( (fun)((int)a, (float) b)) ) -->  fun
STRIP( STRIP( (std::string)(fun)((int)a, (float) b) ) ) --> ( ( int ) a , ( float ) b )

TYPEOF ( ( ( int ) a , ( float ) b ) ) --> ( int ) a , ( float ) b
TYPEOF ( (std::string )( fun )(( int ) a , ( float ) b) ) --> std::string
2.)详细定义的第二个参数

STRIP( (std::string)(fun)((int) a, (float) b) ) --> (fun)((int) a, (float) b)

TYPEOF( (fun)((int)a, (float) b)) ) -->  fun
STRIP( STRIP( (std::string)(fun)((int)a, (float) b) ) ) --> ( ( int ) a , ( float ) b )

TYPEOF ( ( ( int ) a , ( float ) b ) ) --> ( int ) a , ( float ) b
TYPEOF ( (std::string )( fun )(( int ) a , ( float ) b) ) --> std::string
3.)详细定义的第三个参数

STRIP( (std::string)(fun)((int) a, (float) b) ) --> (fun)((int) a, (float) b)

TYPEOF( (fun)((int)a, (float) b)) ) -->  fun
STRIP( STRIP( (std::string)(fun)((int)a, (float) b) ) ) --> ( ( int ) a , ( float ) b )

TYPEOF ( ( ( int ) a , ( float ) b ) ) --> ( int ) a , ( float ) b
TYPEOF ( (std::string )( fun )(( int ) a , ( float ) b) ) --> std::string
结果:

DETAIL_DEFINE ( fun , (( int ) a , ( float ) b), std::string )
顺便说一句,对于那些没有boost\u PP\u VARIADIC\u TO_SEQ的旧boost的用户,请使用 如下所示:

#define BOOST_PP_VARIADIC_TO_SEQ(...) BOOST_PP_TUPLE_TO_SEQ(PP_NARG(__VA_ARGS__) , (__VA_ARGS__))
通过谷歌搜索,你可以在任何地方找到PP_NARG,这是:

//Original Author: Unknown, but well recognized recursive variadic macro
#define PP_NARG(...)        PP_NARG_IMPL(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_IMPL(...)   PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0

<代码>返回<代码>是C++中的保留字——不要将其用作结构成员名称。您想让代码> MyOrthue<代码>扩展到依赖于它后面的内容的东西吗?<代码> MyOyDebug类型名称(类型X,Y类型)< /C> >所需语法?为什么不
MY_DEFINE(type,name,type1,x,type2,y)
或者可能使用可变的最后一部分。不幸的是,我很有信心你提出的语法是不可能的。毕竟,您需要宏具有要使用的参数。现在没有,,并且宏不能查询解析器接下来会看到什么。@ MyWaljson,您是否意识到您不能编辑预处理器生成的任何代码?<代码>返回<代码>是C++中的保留字。不要将其用作结构成员名称。您希望<代码> MyOrdIs>代码>扩展到依赖于它后面的内容的是什么?<代码> MyOyDebug类型。名称(类型x,类型y)所需的语法?为什么不
MY_DEFINE(type,name,type1,x,type2,y)
或者可能使用可变的最后一部分。不幸的是,我很有信心你提出的语法是不可能的。毕竟,您需要宏具有要使用的参数。现在它没有,宏无法查询解析器下一步将看到什么。@myWallJSON您是否意识到您不能编辑预处理器生成的任何代码?为什么要回答这样一个老问题(用一个可接受的答案)?另外,这实际上是一个答案吗?是的,这是一个很好的答案,我在我的项目中使用了这个解决方案,但是我在第一个宏中发现了一个额外的逗号#define TYPEOF(x)DETAIL(DETAIL)TYPEOF(DETAIL)PROBE x,)这里的最后是多余的。为什么你回答了这么老的问题(有一个公认的答案)?另外,这真的是一个答案吗?是的,这是一个很好的答案,我在我的项目中使用了这个解决方案,但是我在第一个宏中发现了一个额外的逗号35; define TYPEOF(x)DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)在最后是多余的