如何用索引序列构造一个 std::array ? [英] How to construct an std::array with index sequence?

查看:40
本文介绍了如何用索引序列构造一个 std::array ?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用索引序列或依赖于顺序索引的 lambda 构建 std::array?

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

std::iotastd::generate 似乎相关,但我不确定如何使用它们来构建 std::array,而不是将它们应用到一个已经构造好的(如果数组的元素类型不是默认构造的,这是不可能的).

std::iota and std::generate seem relevant, but I'm not sure how to use them to construct an std::array, rather then apply them on one which is already constructed (which isn't possible in case the element type of the array isn't default-constructible).

示例我想要 DRY 的代码类型:

Example of the kind of code I'd like to DRY:

#include <array>

class C
{
public:
    C(int x, float f) : m_x{x}, m_f{f} {}
private:
    int m_x;
    float m_f;
};

int main()
{
    std::array<int, 10> ar = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::array<C, 3> ar2 = {C{0, 1.0}, C{1, 1.0}, C{2, 1.0}};
    return 0;
}

推荐答案

对于ar,这里有一个方法:

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

在线演示

对于 ar2,这里有一个方法:

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

在线演示

(noexcept 在 IMO 中或多或少是可选的,为简洁起见,此处省略,但在演示中存在.)

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

注意两者都是完全constexpr,但由于generate_array 很可能与lambdas 一起使用,所以它不会是constexpr 在实践中 直到 C++17(演示).还有 n.b.由于保证复制省略<,generate_array 将适用于 C++17 中的不可复制/不可移动类型(演示).

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).

这篇关于如何用索引序列构造一个 std::array ?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆