How to construct an std::array with index sequence?

后端 未结 2 1148
我在风中等你
我在风中等你 2020-12-14 07:55

How can I construct an std::array with an index sequence, or a lambda which depends on a sequential index?

std::iota and std::generat

相关标签:
2条回答
  • 2020-12-14 08:24

    The next approach should work for you:

    template<typename T, std::size_t N, std::size_t... I>
    constexpr auto create_array_impl(std::index_sequence<I...>) {
        return std::array<T, N>{ {I...} };
    }
    
    template<typename T, std::size_t N>
    constexpr auto create_array() {
        return create_array_impl<T, N>(std::make_index_sequence<N>{});
    }
    

    You can create an array like:

    constexpr auto array = create_array<std::size_t, 4>();
    

    wandbox example

    One can modify the aforementioned solution to add a lambda in the next way:

    template<typename T, std::size_t N, typename F, std::size_t... I>
    constexpr auto create_array_impl(F&& func, std::index_sequence<I...>) {
        return std::array<T, N>{ {func(I)...} };
    }
    
    template<typename T, std::size_t N, typename F>
    constexpr auto create_array(F&& func) {
        return create_array_impl<T, N>(std::forward<F>(func), std::make_index_sequence<N>{});
    }
    

    And then use:

    const auto array = create_array<std::size_t, 4>([](auto e) {
        return e * e;
    });
    

    wandbox example

    0 讨论(0)
  • 2020-12-14 08:35

    For ar, here's an approach:

    namespace detail {
      template<typename T, T... Ns>
      constexpr auto make_iota_array(T const offset, std::integer_sequence<T, Ns...>) noexcept
       -> std::array<T, sizeof...(Ns)> {
        return {{(Ns + offset)...}};
      }
    }
    
    template<typename T, T N>
    constexpr auto make_iota_array(T const offset = {}) noexcept {
      static_assert(N >= T{}, "no negative sizes");
      return detail::make_iota_array<T>(offset, std::make_integer_sequence<T, N>{});
    }
    
    // ...
    
    auto ar = make_iota_array<int, 10>(99);
    

    Online Demo

    For ar2, here's an approach:

    namespace detail {
      template<typename T, typename F, std::size_t... Is>
      constexpr auto generate_array(F& f, std::index_sequence<Is...>)
       -> std::array<T, sizeof...(Is)> {
        return {{f(std::integral_constant<std::size_t, Is>{})...}};
      }
    }
    
    template<typename T, std::size_t N, typename F>
    constexpr auto generate_array(F f) {
      return detail::generate_array<T>(f, std::make_index_sequence<N>{});
    }
    
    // ...
    
    auto ar2 = generate_array<C, 3>([](auto i) -> C { return {i, i * 1.12f}; });
    

    Online Demo

    (noexcept is more-or-less optional here IMO, and omitted here for brevity, but is present in the demos.)

    N.b. both are fully constexpr, but since generate_array is likely to be used with lambdas it won't be constexpr in practice until C++17 (demo). Also n.b. generate_array will work with non-copyable/non-movable types in C++17 due to guaranteed copy elision (demo).

    0 讨论(0)
提交回复
热议问题