我有一个实用宏,用于将给定的宏广播到所有参数:
#define NUM_ARGS_IMPL( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, \
//... many placeholders
_90,_91,_92,_93,_94,_95,_96,_97,_98,_99, \
N, ...) N
#define NUM_ARGS_EXPAND(tuple) NUM_ARGS_IMPL tuple
#define NUM_ARGS(...) NUM_ARGS_EXPAND((__VA_ARGS__, \
99,98,97,96,95,94,93,92,91,90, \
//... many numbers
9,8,7,6,5,4,3,2,1,0 \
))
#define INVOKE_MACRO(macro_name, ...) macro_name(__VA_ARGS__)
#define BROADCAST_1(macro_name, first ) INVOKE_MACRO(macro_name, first)
#define BROADCAST_2(macro_name, first, ...) INVOKE_MACRO(macro_name, first) BROADCAST_1(macro_name, __VA_ARGS__)
#define BROADCAST_3(macro_name, first, ...) INVOKE_MACRO(macro_name, first) BROADCAST_2(macro_name, __VA_ARGS__)
//... go through 1 to 99
#define BROADCAST_99(macro_name, first, ...) INVOKE_MACRO(macro_name, first) BROADCAST_98(macro_name, __VA_ARGS__)
#define BROADCAST_EXPAND(macro_name, N, ...) BROADCAST_ ## N(macro_name, __VA_ARGS__)
#define BROADCAST_N(macro_name, N, ...) BROADCAST_EXPAND(macro_name, N, __VA_ARGS__)
/** uitl macro for broadcasting here */
#define BROADCAST(macro_with_one_param, ...) BROADCAST_N(macro_with_one_param, NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
/** using broadcasting */
#define STR_OSTREAM(msg) <<(msg)
#define STR_OSTREAMs(...) BROADCAST(STR_OSTREAM, __VA_ARGS__) // broadcast STR_OSTREAM on all arguments
#define SSTR(var, ...) \
std::string var; \
{ \
std::stringstream ss; \
ss STR_OSTREAMs(__VA_ARGS__); \
var = ss.str(); \
}
#endif
通过使用它:
SSTR(info, 1, 2, 3, 4);
std::cout << info;
g++ 给出:
std::string info; { std::stringstream ss; ss <<(1) <<(2) <<(3) <<(4); info = ss.str(); }
但是在视觉工作室中:
std::string info; { std::stringstream ss; ss <<(1) <<(2, 3, 4) <<() <<(); info = ss.str(); }
不确定是这样的宏兼容性不够还是只是编译器设置的问题?我怎样才能做到正确?
我怎样才能做到正确?
一种方法当然是删除所有宏内容并用它替换它。
(由于 C++11 没有折叠表达式,因此发生了一些可变参数扩展技巧)
template<typename ...Args>
inline std::string SSTR(const Args& ...args)
{
std::stringstream ss; using x = void*[]; (void)x{&(ss << args)...}; return ss.str();
}
这将允许
auto info = SSTR(1, 2, 3, 4);
std::cout << info;
输出
1234