【问题标题】:Dont expand BOOST_PP_SEQ_FOR_EACH if SEQ is empty如果 SEQ 为空,则不要扩展 BOOST_PP_SEQ_FOR_EACH
【发布时间】:2023-03-11 13:32:01
【问题描述】:

如果参数列表为空

#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_ 为空,我希望它扩展为空。 This 回答了这种类型的问题,但如果我使用它来代替

#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 在别处使用,这意味着它已定义。

【问题讨论】:

    标签: c boost c-preprocessor


    【解决方案1】:

    我不知道。

    我知道

    • 宏经常有问题
    • 花括号组表达式是非标准的

    看起来您正在尝试将多个积分信号组合成一个键掩码,因此组成一个示例可能如下所示:

    enum SigKeys {
        key0 = 1,
        key1 = 2,
        key2 = 4,
        key3 = 8,
        key4 = 16,
    };
    

    Live On Coliru

    #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));
    }
    

    它将是标准的、可移植的、在很短的时间内编译、更具可读性、contexpr 和optimizable

    Live On Coliru

    如果你的编译器老了会怎样

    即使这样你也可以拥有更好的:

    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。不出所料,它会optimize just the same

    如果您喜欢不使用 std::accumulateColiruCompiler Explorer

    ComponentKey getKey(std::initializer_list<int> sig) {
        ComponentKey r = 0;
        for (auto& s : sig)
            r |= 1 << s;
        return r;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      • 2019-11-17
      • 1970-01-01
      相关资源
      最近更新 更多