代码之家  ›  专栏  ›  技术社区  ›  Amos

由于constexpr不可捕获,嵌套的静态循环无法工作

  •  -2
  • Amos  · 技术社区  · 6 年前

    static_loop 用于循环展开上的类型分派的构造。

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

    i j 两者都是 constexpr 因此 i * j std::get<> 然而,编译器似乎不允许这样做。有可能抓到吗 作为内部lambda中的constexpr?

    完整的例子是 godbolt 以及错误消息。

    2 回复  |  直到 6 年前
        1
  •  1
  •   xeros    6 年前
    static_loop<2>([&](auto i) {
        std::get<i>(ab) = i;
        static_loop<2>([&](auto j) { std::get<i * j>(ab) }
    }
    

    IDE为您正确地强调了错误。 i * j 是两个变量的乘法,它不是编译时常量。

        2
  •  0
  •   Amos    6 年前

    这在某种程度上起作用了。不确定是否违反了任何标准规则。

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