如果 SEQ 为空,则不要扩展 BOOST_PP_SEQ_FOR_EACH
Dont expand BOOST_PP_SEQ_FOR_EACH if SEQ is empty
如果参数列表为空
#define key_evaluate(r, key, sig) key |= 1 << sig;
#define getKey(...)\
({\
ComponentKey key = 0;\
BOOST_PP_SEQ_FOR_EACH(key_evaluate, key, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
key;\
})
int main(void)
{
getKey();
}
扩展到
int main(void)
{
({
ComponentKey key = 0;
key |= 1 << ;
key;
})
}
但如果 _VA_ARGS_ 为空,我希望将其展开为空。
回答了此类问题,但如果我改用它
#define key_evaluate(r, key, sig) key |= 1 << sig;
#define convertToKey(...) BOOST_PP_SEQ_FOR_EACH(key_evaluate, key, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
#define components_convertToKey(...)\
({\
ComponentKey key = 0;\
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE((,##__VA_ARGS__)), 1), \
BOOST_PP_EXPAND, convertToKey) (__VA_ARGS__) \
key;\
})
我收到此错误:error: ‘BOOST_PP_EXPAND’ undeclared
。
这意味着 BOOST_PP_EXPAND 没有被预处理器替换,因为 BOOST_PP_EXPAND 在其他地方使用,这意味着它是定义的。
我不知道。
我知道
- 宏经常有问题
- 大括号表达式是非标准的
您似乎在尝试将多个整数信号组合成一个密钥掩码,因此构成一个示例可能如下所示:
enum SigKeys {
key0 = 1,
key1 = 2,
key2 = 4,
key3 = 8,
key4 = 16,
};
#include <iostream>
int main(void) {
std::cout << "key1, key2: " << (key1 + key2) << " == " << getKey(1, 2) << "\n";
std::cout << "key2, key4: " << (key2 + key4) << " == " << getKey(4, 2) << "\n";
}
版画
key1, key2: 6 == 6
key2, key4: 20 == 20
重拍,无宏
假设您的编译器符合要求,您可以简单地将其写为:
template <typename... T>
constexpr ComponentKey getKey(T&&... sig) {
return (0 | ... | (1 << sig));
}
它将是标准的、可移植的、编译时间很短、更具可读性、conexpr 和 optimizable。
如果你的编译器旧了怎么办
即便如此你也可以拥有更好的:
ComponentKey getKey(std::initializer_list<int> sig) {
return std::accumulate(sig.begin(), sig.end(), 0,
[](int r, int s) { return r | (1 << s); });
}
看到了Live On Coliru as well. Unsurprisingly it will optimize just the same.
If you prefer without std::accumulate
: Coliru and Compiler Explorer
ComponentKey getKey(std::initializer_list<int> sig) {
ComponentKey r = 0;
for (auto& s : sig)
r |= 1 << s;
return r;
}
如果参数列表为空
#define key_evaluate(r, key, sig) key |= 1 << sig;
#define getKey(...)\
({\
ComponentKey key = 0;\
BOOST_PP_SEQ_FOR_EACH(key_evaluate, key, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
key;\
})
int main(void)
{
getKey();
}
扩展到
int main(void)
{
({
ComponentKey key = 0;
key |= 1 << ;
key;
})
}
但如果 _VA_ARGS_ 为空,我希望将其展开为空。
#define key_evaluate(r, key, sig) key |= 1 << sig;
#define convertToKey(...) BOOST_PP_SEQ_FOR_EACH(key_evaluate, key, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
#define components_convertToKey(...)\
({\
ComponentKey key = 0;\
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE((,##__VA_ARGS__)), 1), \
BOOST_PP_EXPAND, convertToKey) (__VA_ARGS__) \
key;\
})
我收到此错误:error: ‘BOOST_PP_EXPAND’ undeclared
。
这意味着 BOOST_PP_EXPAND 没有被预处理器替换,因为 BOOST_PP_EXPAND 在其他地方使用,这意味着它是定义的。
我不知道。
我知道
- 宏经常有问题
- 大括号表达式是非标准的
您似乎在尝试将多个整数信号组合成一个密钥掩码,因此构成一个示例可能如下所示:
enum SigKeys {
key0 = 1,
key1 = 2,
key2 = 4,
key3 = 8,
key4 = 16,
};
#include <iostream>
int main(void) {
std::cout << "key1, key2: " << (key1 + key2) << " == " << getKey(1, 2) << "\n";
std::cout << "key2, key4: " << (key2 + key4) << " == " << getKey(4, 2) << "\n";
}
版画
key1, key2: 6 == 6
key2, key4: 20 == 20
重拍,无宏
假设您的编译器符合要求,您可以简单地将其写为:
template <typename... T>
constexpr ComponentKey getKey(T&&... sig) {
return (0 | ... | (1 << sig));
}
它将是标准的、可移植的、编译时间很短、更具可读性、conexpr 和 optimizable。
如果你的编译器旧了怎么办
即便如此你也可以拥有更好的:
ComponentKey getKey(std::initializer_list<int> sig) {
return std::accumulate(sig.begin(), sig.end(), 0,
[](int r, int s) { return r | (1 << s); });
}
看到了Live On Coliru as well. Unsurprisingly it will optimize just the same.
If you prefer without
std::accumulate
: Coliru and Compiler ExplorerComponentKey getKey(std::initializer_list<int> sig) { ComponentKey r = 0; for (auto& s : sig) r |= 1 << s; return r; }