- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
只是为了了解一点背景知识,这不是一个微不足道的练习!我正在使用 Boost.Python,为了避免大量丑陋的样板代码,我使用宏将函数包装在 Python 包装器类中,以选择性地为该方法调用 Python 重写(如果存在)。
我已将难题归结为最简单的形式,here :
#include <iostream>
using namespace std;
void foo() { cout << "foo" << endl; }
void bar(char, short, int) { cout <<"bar" << endl; }
#define DEFINE_FUNCTION_WRAPPER(return_type, name, ...)\
return_type name##_wrapper(/* macro expansion */)\
{\
return name(/* macro expansion */);\
}\
DEFINE_FUNCTION_WRAPPER(void, foo) // works!
//DEFINE_FUNCTION_WRAPPER(void, foo, char, short, int) // knowledge insufficient
int main() {
foo_wrapper();
//bar_wrapper(0, 1, 2);
}
虽然这显然适用于 foo
,但我的目标是让 DEFINE_FUNCTION_WRAPPER(void, foo, char, short, int)
生成如下所示的函数包装器:
void bar_wrapper(char _1, short _2, int _3)
{
return bar(_1, _2, _3);
}
我希望找到正确的方向来解决这个问题,因为我真的很想掌握这种宏观魔法。
感谢任何帮助!
NOTE: I'm compiling against 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();}
BOOST_PP_ENUM
用递增的数字调用给定的宏,我们在 PARAMS
宏中使用它作为类型元组(传入的数据)和姓名。它还在扩展之间放置逗号,但不是在最后一个之后。您可以在代码注释中看到它的扩展。如果需要,可以忽略 z
。
BOOST_PP_ENUM_PARAMS
保存了单独宏的工作,而是采用“常量”来附加数字。它还在扩展之间放置逗号。我们使用下划线以 _0、_1、_2 结尾。
关于python - 使用宏从 __VA_ARGS__ 生成参数列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31845839/
我有以下两个宏: #define F1(...) [NSString stringWithFormat:__VA_ARGS__] #define F2(format, ...) [NSString s
我想知道##在这个宏定义中做了什么: #define debug(M, ...) fprintf(stderr,M "\n",##__VA_ARGS __) 我在谷歌上搜索了答案,并得出了以下结果。
C++ preprocessor __VA_ARGS__ number of arguments 那里接受的答案对我不起作用。我试过 MSVC++ 10 和 g++ 3.4.5。 我还将示例压缩成更小
此代码片段是否可移植? 定义: #define log(...) std::cout << __FILE__ << "[" << __LINE__ << "]:" \
在可变参数宏中,#__VA_ARGS__是所有参数的逗号分隔字符串(至少我用 gcc 和 clang 得到了这种行为)。有没有一种方法可以在不解析该字符串的情况下为各个参数创建一个字符串数组? 我正在
我有以下宏: #define MY_FCT1( id, ... ) \ FCT( id,__VA_ARGS__ ); \ 我想创建一个新的来做这样的事情: #de
variadic macro提到了 gcc 的 VA_ARGS。 我做了以下实验。 #define EVAL(f,...) eval(f,build_args(args,__VA_ARGS__ , a
我知道我可以做到: #define MACRO(api, ...) \ bool ret = api(123, ##__VA_ARGS__); 这只是一个示例,它是更复杂解决方案的一部分。关键是我
我正在尝试为数组数据冗余编写一个特殊的类型处理。这个想法是在编译时全局定义和声明一个固定大小的数组,但每个声明的数组的大小都不同。这是想法: array[N] = { el1, el2, el3, .
我正在尝试制作一个类似于此的函数: #define printf_copy(s, ...) printf(s, ##__VA_ARGS__) // acceptable! 但这是一个预处理器,我需
如果我尝试编译以下代码: template void Dummy(const TArgs &...args) { } #define DUMMY(...) Dummy("Hello", ##__VA
我想定义一个宏,例如 - #define log(lognumber,...) logreport(lognumber,__VA_ARGS__) 我想检查 __VA_ARGS__ 用户调用 log
假设我们有以下两个函数: void foo1(int p); void foo2(int p, ...); 我想编写一个宏,根据参数的数量自动扩展为正确的宏。我使用了以下肮脏/黑客的方式,但我很好奇是
假设我有一个宏: #define FOO(a, ...) if (a) foo(a, ## __VA_ARGS__) 这很好用: FOO(a)将转换为 if (a) foo(a) FOO(a, )将转
只是为了了解一点背景知识,这不是一个微不足道的练习!我正在使用 Boost.Python,为了避免大量丑陋的样板代码,我使用宏将函数包装在 Python 包装器类中,以选择性地为该方法调用 Pytho
我正在尝试重新定义可变参数宏以使用 cout 而不是 printf。这是原始代码: #define LOGE(...) PRINT_LEVEL(1, __VA_ARGS__); #define P
我正在尝试将 __ VA_ARGS __ 传递给一个函数。由于某种原因,第一个参数总是错误的(看起来像一个地址): #define PRINTF_ERROR(format, ...) {\
我已经从互联网上下载并重新编译了一个库,结果是由于非法指针地址导致核心转储。 查看源码,涉及的语句有: #define E_DEBUG(level, ...) \ if (err_get_de
我正在开发一个嵌入式应用程序,它使用一个库来连接 SPI NAND 内存芯片。提供的库使用打印功能,作为应用程序开发人员,我必须针对我的特定平台覆盖该功能。 例如,他们在代码中广泛使用函数 print
我正在为 SQL 代码使用预处理器宏 va_args hack,以允许直接粘贴到 sqlite3.exe 中以进行快速的非构建调试: #define QUOTE(...) #__VA_ARGS__ c
我是一名优秀的程序员,十分优秀!