Invalid explicitly-specified argument for template parameter which is constexpr

后端 未结 2 1110
生来不讨喜
生来不讨喜 2021-01-23 08:08

I have a static_loop construct like this

template  void static_loop(F&& f) {
    static_assert(n <= 8 &a         


        
相关标签:
2条回答
  • 2021-01-23 08:41

    Change

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

    to:

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

    That is, take the argument by reference to const, not by value. As-is, you're trying to copy a non-constexpr tuple in a constant expression - that can't work. By reference is fine since you're not actually reading the tuple.

    0 讨论(0)
  • 2021-01-23 08:54

    Suggestion: try with

    // .........VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
    static_loop<std::tuple_size_v<decltype(ab)>>([&](auto i) { std::get<i>(ab) = i; });
    

    I mean... you can't use ab (as value), in a constant expression, because ab isn't defined constexpr.

    And you can't define it constexpr because it's initialized using std::ref() that isn't constexpr.

    But you're not interested in ab as value to get the size of its type; you're interested only in ab type; so you can pass through decltype(ab).

    -- EDIT --

    Off Topic suggestion.

    Instead of static_loop(), you can use the classic way based on std::index_sequence (and template folding, available starting from C++17).

    I mean... if you define a run_1() function (with run_1_helper() helper) as follows

    template <typename F, typename ... Ts, std::size_t ... Is>
    void run_1_helper (F const & f, std::tuple<Ts...> & t, std::index_sequence<Is...> const)
     { (f(std::get<Is>(t), Is), ...); }
    
    template <typename F, typename ... Ts>
    void run_1 (F const & f, std::tuple<Ts...> & t)
     { run_1_helper(f, t, std::index_sequence_for<Ts...>{}); }
    

    you can write A as follows

    struct A {
        int a;
        int b;
        void run() {
            auto ab = std::make_tuple(std::ref(a), std::ref(b));
            run_1([](auto & v, auto i){ v = i; }, ab);
            std::cout << a << " " << b << std::endl;
        }
    };
    

    Or, maybe better, simply using std::apply(), as follows

    struct A {
        int a;
        int b;
        void run() {
            auto ab = std::make_tuple(std::ref(a), std::ref(b));
            int i { -1 };
            std::apply([&](auto & ... vs){ ((vs = ++i), ...); }, ab);
            std::cout << a << " " << b << std::endl;
        }
    };
    
    0 讨论(0)
提交回复
热议问题