Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用宏从_VA_参数生成参数列表___Python_C++_C++11_Boost_Macros - Fatal编程技术网

Python 使用宏从_VA_参数生成参数列表__

Python 使用宏从_VA_参数生成参数列表__,python,c++,c++11,boost,macros,Python,C++,C++11,Boost,Macros,仅举一点背景,这不是一个简单的练习!我使用的是Boost.Python,为了避免大量难看的样板代码,我使用宏将函数包装在Python包装类中,如果方法存在,可以选择调用Python重写 我把这个难题归结为最简单的形式: 我期待着在如何最好地解决这个问题上被指出正确的方向,因为我真的很想掌握这种宏观魔术 感谢您的帮助 注意:我是针对MSVC C++11进行编译的 假设您确实需要宏(我对Boost.Python不太熟悉,但可变模板和完美转发与此相同,如果适用,则更简洁),您可以使用几个方便的Boos

仅举一点背景,这不是一个简单的练习!我使用的是Boost.Python,为了避免大量难看的样板代码,我使用宏将函数包装在Python包装类中,如果方法存在,可以选择调用Python重写

我把这个难题归结为最简单的形式:

我期待着在如何最好地解决这个问题上被指出正确的方向,因为我真的很想掌握这种宏观魔术

感谢您的帮助

注意:我是针对MSVC C++11进行编译的


假设您确实需要宏(我对Boost.Python不太熟悉,但可变模板和完美转发与此相同,如果适用,则更简洁),您可以使用几个方便的Boost.Preprocessor工具

问题是,宏末尾的省略号必须至少传递一个参数;它不可能是零。要解决这个问题,您必须在某个地方至少放弃一个参数名。我选择让宏根据是否得到任何与参数相关的参数来填充省略号,从另外两个参数中选择一个

#include <boost/preprocessor.hpp>

//generate "type _#"
#define PARAMS(z,n,data) BOOST_PP_TUPLE_ELEM(n,data) _##n

//The first variant: with parameters
//parameters: PARAMS(z,0,(char,short,int)), PARAMS(z,1,(char,short,int)), PARAMS(z,2,(char,short,int))
//call: _0, _1, _2

#define DEFINE_FUNCTION_WRAPPER_WITH_PARAMS(return_type, name, ...)\
return_type name##_wrapper(BOOST_PP_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), PARAMS, (__VA_ARGS__)))\
{\
    return name(BOOST_PP_ENUM_PARAMS(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), _));\
}

//The second variant: no parameters
#define DEFINE_FUNCTION_WRAPPER_WITHOUT_PARAMS(return_type, name)\
return_type name##_wrapper()\
{\
    return name();\
}

//choose variant based on whether more than two arguments are passed
#define DEFINE_FUNCTION_WRAPPER(...)\
    BOOST_PP_IF(\
        BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 2), \
        DEFINE_FUNCTION_WRAPPER_WITH_PARAMS,\
        DEFINE_FUNCTION_WRAPPER_WITHOUT_PARAMS\
    )(__VA_ARGS__)

//Clang output:
//void foo_wrapper( char _0 , short _1 , int _2){ return foo( _0 , _1 , _2);}
//int bar_wrapper(){ return bar();}
#包括
//生成“类型”
#定义参数(z,n,data)BOOST_PP_TUPLE_ELEM(n,data)35; n
//第一个变量:带参数
//参数:PARAMS(z,0,(char,short,int)),PARAMS(z,1,(char,short,int)),PARAMS(z,2,(char,short,int))
//呼叫:_0、_1、_2
#使用参数(返回类型、名称等)定义函数包装器\
返回类型名称###(BOOST#u PP_ENUM(BOOST_PP_VARIADIC_SIZE(uu VA_ARGS_u))、参数、(u VA_ARGS_u)))\
{\
返回名称(BOOST_PP_ENUM_参数(BOOST_PP_可变大小(uu VA_ARGS_u),u))\
}
//第二种变体:无参数
#定义不带参数的函数包装(返回类型、名称)\
返回类型名称###包装器()\
{\
返回名称()\
}
//根据是否传递两个以上的参数选择变量
#定义函数包装器(…)\
如果需要,则增强(\
BOOST_PP_更大(BOOST_PP_可变大小(uu VA_ARGS_uu),2)\
使用参数定义函数包装器\
定义没有参数的函数包装器\
)(uu VA_uargs_uu)
//叮当声输出:
//void foo_包装(char 0,short 1,int 2){返回foo(0,1,2);}
//int bar_wrapper(){return bar();}
BOOST_PP_ENUM
以递增的数字调用给定的宏,我们在
PARAMS
宏中使用它作为类型元组(传入的数据)和名称的索引。它还将逗号放在扩展之间,但不能放在最后一个扩展之后。您可以在代码注释中看到它的扩展<如果需要,可以忽略代码>z


BOOST_PP_ENUM_PARAMS
保存一个单独宏的工作,而是使用“常量”将数字附加到其中。它还将逗号放在扩展之间。我们使用下划线以_0、_1、_2结尾

如果
bar(char,short,int)
存在,那么
bar\u wrapper
作为它的确切别名有什么意义呢?请阅读文章的开头。这是一个非平凡实现的平凡示例。可能需要一个不那么平凡的示例。我看不到使用宏的必要性。一架飞机正在坠毁,数百人将死亡,除非我使用宏生成这个函数包装器!除了开玩笑,所提供的示例的琐碎性丝毫不会妨碍我理解我试图完成的基本任务。看起来它会起作用,尽管我需要制定一些非常小的编译器标志,以便在MSVC上调用
BOOST\u PP\u VARIADIC\u SIZE
。@cmbasnett,MSVC以其不太完美的预处理器而闻名。据我所知,Boost.PP的大部分或全部都有解决办法。@cmbasnett,如果出现最坏的情况,并且没有定义Boost\u PP\u VARIADICS或其他什么,然后,您可以让包装器宏获取其给定的类型数,并使用带有大小参数的
TUPLE\u ELEM
。我已经找到了它未定义的原因:需要未定义
\uuuuu EDG\uuuu
编译器标志。不确定这到底是什么,但我的浏览告诉我,
#undef
是相当安全的,这可能是MSVC中的一个bug。嗯,你的
定义函数包装器
与无参数函数包装器一起工作吗?当它试图包装这些错误时,我收到了很多未定义的错误。
void bar_wrapper(char _1, short _2, int _3)
{
    return bar(_1, _2, _3);
}
#include <boost/preprocessor.hpp>

//generate "type _#"
#define PARAMS(z,n,data) BOOST_PP_TUPLE_ELEM(n,data) _##n

//The first variant: with parameters
//parameters: PARAMS(z,0,(char,short,int)), PARAMS(z,1,(char,short,int)), PARAMS(z,2,(char,short,int))
//call: _0, _1, _2

#define DEFINE_FUNCTION_WRAPPER_WITH_PARAMS(return_type, name, ...)\
return_type name##_wrapper(BOOST_PP_ENUM(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), PARAMS, (__VA_ARGS__)))\
{\
    return name(BOOST_PP_ENUM_PARAMS(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), _));\
}

//The second variant: no parameters
#define DEFINE_FUNCTION_WRAPPER_WITHOUT_PARAMS(return_type, name)\
return_type name##_wrapper()\
{\
    return name();\
}

//choose variant based on whether more than two arguments are passed
#define DEFINE_FUNCTION_WRAPPER(...)\
    BOOST_PP_IF(\
        BOOST_PP_GREATER(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 2), \
        DEFINE_FUNCTION_WRAPPER_WITH_PARAMS,\
        DEFINE_FUNCTION_WRAPPER_WITHOUT_PARAMS\
    )(__VA_ARGS__)

//Clang output:
//void foo_wrapper( char _0 , short _1 , int _2){ return foo( _0 , _1 , _2);}
//int bar_wrapper(){ return bar();}