C++ 如何用range-v3中的范围填充std::array?

C++ 如何用range-v3中的范围填充std::array?,c++,c++20,range-v3,C++,C++20,Range V3,我是range-v3库的完全初学者。。假设我想在某个间隔内用随机数填充std::array 对于迭代器,我会做一些类似的事情,将迭代器作为参数传递给我的std::array template< class Iter > void fill_with_random_int_values( Iter start, Iter end, int min, int max) { static std::random_device rd; // you only need to i

我是range-v3库的完全初学者。。假设我想在某个间隔内用随机数填充
std::array

对于迭代器,我会做一些类似的事情,将迭代器作为参数传递给我的
std::array

template< class Iter >
void fill_with_random_int_values( Iter start, Iter end, int min, int max)
{
    static std::random_device rd;    // you only need to initialize it once
    static std::mt19937 mte(rd());   // this is a relative big object to create

    std::uniform_int_distribution<int> dist(min, max);

    std::generate(start, end, [&] () { return dist(mte); });
}

这对于
std::vector
很有效,但我不知道应该使用什么算法来填充
std::array
,而不是生成
std::vector
,因为上面类似的方法不起作用。我可以
转换
数组并忽略每个参数,但这似乎不正确

std::array的大小是一个编译时常量,因此我看不出库如何使用运行时参数为您生成一个

下面是一个相当简单的实现,我认为它满足了您的需要:

#include <random>
#include <array>
#include <utility>
#include <iostream>

auto random_num() -> int {
  static std::mt19937 engine{std::random_device{}()};
  static std::uniform_int_distribution<int> dist(1, 10);
  return dist(engine);
}

template<class F, std::size_t...Is>
auto generate_array_impl(F&& f, std::index_sequence<Is...>) -> std::array<decltype(f()), sizeof...(Is)>
{
    return std::array<decltype(f()), sizeof...(Is)>
    {{
        (void(Is), f())...
    }};
}

template<std::size_t N, class F>
auto generate_array(F f) -> std::array<decltype(f()), N>
{
    return generate_array_impl(f, std::make_index_sequence<N>());
}


int main()
{
    auto arr = generate_array<10>(random_num);
    for (auto x : arr)
    std::cout << x << '\n';
}
#包括
#包括

或者添加一些constexpr魔法

#include <random>
#include <array>
#include <utility>
#include <iostream>
#include <boost/range.hpp>

template<std::size_t N>
constexpr auto c_size_t = std::integral_constant<std::size_t, N>();

auto random_num() -> int {
  static std::mt19937 engine{std::random_device{}()};
  static std::uniform_int_distribution<int> dist(1, 10);
  return dist(engine);
}

template<class F, std::size_t...Is>
constexpr auto generate_array_impl(F&& f, std::index_sequence<Is...>) -> std::array<decltype(f()), sizeof...(Is)>
{
    return std::array<decltype(f()), sizeof...(Is)>
    {{
        (void(Is), f())...
    }};
}

template<std::size_t N, class F>
constexpr auto generate_array(F&& f, std::integral_constant<std::size_t, N>) -> std::array<decltype(f()), N>
{
    return generate_array_impl(f, std::make_index_sequence<N>());
}

int main()
{
    auto arr = generate_array(random_num, c_size_t<10>);
    for (auto x : arr)
        std::cout << x << ',';
    std::cout << '\n';

    constexpr auto arr2 = generate_array([i = std::size_t(0)]() mutable { return i++; }, c_size_t<10>);
    for (auto x : arr2)
        std::cout << x << ',';
    std::cout << '\n';
}
#包括

#include

std::array
是一个聚合;它没有用户提供的构造函数。因此,它没有从范围创建对象的构造函数

您也不能(在C++17中)编写一个接受范围并返回数组的函数。原因是参数不是
constexpr
,数组的大小必须是常量表达式。C++20似乎增加了将更多类型作为非类型模板参数的功能,因此应该可以将其作为模板参数。代码如下所示:

template<auto rng>
    requires std::ranges::sized_range<decltype(rng)>
constexpr auto array_from_range()
{
  std::array<std::iter_value_t<decltype(rng)>, std::ranges::size(rng)> ret;
  std::ranges::copy(rng, ret);
  return ret;
}
模板
需要std::ranges::sized_range
constexpr自动数组_from_range()
{
std::数组ret;
标准::范围::副本(rng、ret);
返回ret;
}

当然,这要求范围本身是
constexpr
,而不仅仅是它的大小。

,因为数组的大小是编译时常量。你必须自己建造它。你可以把它填好

std::array<int, 10> arr;
ranges::generate(arr, random_num);
std::数组arr;
范围::生成(arr,random_num);
另请参见
std::array<int, 10> arr;
ranges::generate(arr, random_num);