【问题标题】:Why if constexpr fails to bypass constexpr evaluation?为什么如果 constexpr 未能绕过 constexpr 评估?
【发布时间】:2018-12-30 13:00:39
【问题描述】:

我正在为使用宏进行类型分派构建一个静态循环。这是 到目前为止我所取得的成就。

#define LOOP(n, f)                                            \
    static_assert(n <= 8 && "static loop size should <= 8");  \
    do {                                                      \
        if constexpr (n >= 8)                                 \
            f(std::integral_constant<size_t, n - 8>());       \
        if constexpr (n >= 7)                                 \
            f(std::integral_constant<size_t, n - 7>());       \
        if constexpr (n >= 6)                                 \
            f(std::integral_constant<size_t, n - 6>());       \
        if constexpr (n >= 5)                                 \
            f(std::integral_constant<size_t, n - 5>());       \
        if constexpr (n >= 4)                                 \
            f(std::integral_constant<size_t, n - 4>());       \
        if constexpr (n >= 3)                                 \
            f(std::integral_constant<size_t, n - 3>());       \
        if constexpr (n >= 2)                                 \
            f(std::integral_constant<size_t, n - 2>());       \
        if constexpr (n >= 1)                                 \
            f(std::integral_constant<size_t, n - 1>());       \
    } while (0);

template <typename T> constexpr size_t tupleSize(T&) { return tuple_size_v<T>; }

int main() {
    auto t = std::make_tuple(1, "string", 0.2, 3, 1, 1, 1);
    LOOP(tupleSize(t), [&](auto i) { cout << std::get<i>(t) << endl; });
    return 0;
}

还有神螺栓链接https://godbolt.org/z/GcMZI3

问题是,为什么前四个分支编译失败?

【问题讨论】:

  • Realted:stackoverflow.com/questions/46512248/… - 与我的问题相同,您的问题不依赖。事实上,它甚至不是模板。
  • #define 是什么?因此,整个 LOOP 应该是空的。
  • @appleapple - 向右滚动代码。 \ 休息在那里。
  • @StoryTeller 哦!谢谢,也许最好放近一点。
  • 顺便说一句,static_assert 接受第二个字符串文字参数。无需使用与 C 断言宏相同的技巧。你可以写这个static_assert(n &lt;= 8, "static loop size should &lt;= 8");

标签: c++ c++17 constexpr if-constexpr


【解决方案1】:

不要使用宏,而是使用函数模板。 if constexpr 的工作原理是丢弃未采用的分支,具体取决于模板的当前实例化

template <std::size_t n, typename F>
void loop(F&& f)
{
    static_assert(n <= 8 && "static loop size should <= 8");
    if constexpr (n >= 8)
        f(std::integral_constant<size_t, n - 8>());
    if constexpr (n >= 7)
        f(std::integral_constant<size_t, n - 7>());
    if constexpr (n >= 6)
        f(std::integral_constant<size_t, n - 6>());
    if constexpr (n >= 5)
        f(std::integral_constant<size_t, n - 5>());
    if constexpr (n >= 4)
        f(std::integral_constant<size_t, n - 4>());
    if constexpr (n >= 3)
        f(std::integral_constant<size_t, n - 3>());
    if constexpr (n >= 2)
        f(std::integral_constant<size_t, n - 2>());
    if constexpr (n >= 1)
        f(std::integral_constant<size_t, n - 1>());
}

用法:

int main() {
    constexpr auto t = std::make_tuple(1, "string", 0.2, 3);
    loop<tupleSize(t)>([&](auto i) { cout << std::get<i>(t) << endl; });
    return 0;
}

live example on godbolt.org


来自cppreference

如果 constexpr if 语句出现在模板化实体中,并且 if 条件在实例化后不依赖于值,则在实例化封闭模板时不会实例化丢弃的语句。

在模板之外,完全检查丢弃的语句。 if constexpr 不能替代#if 预处理指令

【讨论】:

猜你喜欢
  • 2017-06-27
  • 1970-01-01
  • 2016-08-30
  • 2020-10-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 2015-02-25
相关资源
最近更新 更多