Nested static loop fails to work due to constexpr uncapturable

别说谁变了你拦得住时间么 提交于 2019-12-13 09:33:21

问题


I have this static_loop construct that is used for type dispatching over loop unrolling.

template <std::size_t n, typename F> void static_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>());
}

template <typename T> constexpr size_t tupleSize(T) { return tuple_size_v<T>; }
struct A {
    int a;
    int b;
    void run() {
        auto ab = std::make_tuple(std::ref(a), std::ref(b));
        static_loop<2>([&](auto i) {
            std::get<i>(ab) = i;
            static_loop<2>([&](auto j) { std::get<i * j>(ab) = i; });
            // static_loop<2>([&, i = std::integral_constant<size_t, i>()](auto j) { std::get<i * j>(ab) = i; });
        });
        std::cout << a << " " << b << std::endl;
    }
};

However it doesn't compile when doing nested loops. I'd assume i and j are both constexpr thus i * j is valid in std::get<>, however, compiler seems not allowing this. Is it possible to capture i as constexpr in the inner lambda?

Full example is at godbolt along with the error messages.


回答1:


static_loop<2>([&](auto i) {
    std::get<i>(ab) = i;
    static_loop<2>([&](auto j) { std::get<i * j>(ab) }
}

The IDE correctly underlines the error for you. i * jis a multiplication of two variables, it is not a compile-time constant.

You can nest loops if you switch to template parameters rather than function arguments.




回答2:


This somehow works. Not sure if it violates any standard rules.

template <std::size_t n, typename F> void static_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>());
}

struct A {
    int a;
    int b;
    void run() {
        auto ab = std::make_tuple(std::ref(a), std::ref(b));
        static_loop<2>([&](auto i) {
            std::get<i>(ab) = i;
            static_loop<2>([&](auto j) { auto ii = decltype(i)(); std::get<ii * j>(ab) = ii; });
        });
        std::cout << a << " " << b << std::endl;
    }
};

The captured value might not be constexpr but its type is somehow retained.



来源:https://stackoverflow.com/questions/53978389/nested-static-loop-fails-to-work-due-to-constexpr-uncapturable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!