g++ 和 msvc 之间的宏扩展不同

问题描述 投票:0回答:1

我有一个实用宏,用于将给定的宏广播到所有参数:

#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++ c++11 visual-c++ macros g++
1个回答
0
投票

我怎样才能做到正确?

一种方法当然是删除所有宏内容并用它替换它。

(由于 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
© www.soinside.com 2019 - 2024. All rights reserved.