如何构造一个充满一些统一值的 std::array ?

问题描述 投票:0回答:2

std::array
可以用特定值构造(在较新的 C++ 版本的编译时),例如

std::array a{1, 4, 9};

但是 - 它没有构造函数,也没有标准库命名的构造函数习惯用法,采用单个值并复制它。即我们没有:

std::array<int, 3> a{11};
// a == std::array<int, 3>{11, 11, 11};

因此,我们如何构造一个只给出要重复的值的数组?

编辑:我正在寻找一种解决方案,即使对于不可默认构造的元素类型也适用;因此,通过默认构造数组然后填充它的解决方案不是我所追求的 - 尽管事实上这适用于

int
的情况(如示例中所示)。

c++ arrays stdarray
2个回答
8
投票

我们可以编写一个适当的命名构造函数习惯用法来实现这一点。然后,您的示例定义将如下所示:

auto a = array_repeat<3>(11);
// a == std::array<int, 3>{11, 11, 11};

但是,实现有点笨拙,因为我们需要使用 “索引技巧”,这在 C++11 中需要大量样板,所以让我们假设 C++14:

namespace detail {

template<size_t, class T>
constexpr T&& identity(T&& x) { return std::forward<T>(x); }

template<class T, size_t... Indices>
constexpr auto array_repeat_impl(T&& x, std::index_sequence<Indices...>)
{
    return std::experimental::make_array(identity<Indices>(x)...);
}

} // end detail

template<size_t N, class T>
constexpr auto array_repeat(T&& x)
{
    return detail::array_repeat_impl(std::forward<T>(x), std::make_index_sequence<N>());
}

请参阅此工作GodBolt

如果你可以编译你的代码 C++20,你可以删除对

make_array
的依赖并编写:

namespace detail {

template<size_t, class T>
constexpr T&& identity(T&& x) { return std::forward<T>(x); }

template<class T, size_t... Indices>
constexpr auto array_repeat_impl(T&& x, std::index_sequence<Indices...>)
{
    return std::array{identity<Indices>(x)...};
}

} // end detail

template<size_t N, class T>
constexpr auto array_repeat(T&& x)
{
    return detail::array_repeat_impl(std::forward<T>(x), std::make_index_sequence<N>());
}

神螺栓

备注:

  • 此解决方案有点类似于 Jared Hoberock 的
    tuple_repeat
    ,它是他的 C++11 元组实用程序的一部分。
  • 感谢@Caleth 和@L.F.指出
  • array_repeat_impl
     中的不当转发。
  • array_repeat()
    函数可以获取右值引用并从中移动,因此可以在参数中创建临时值,即使它很昂贵。

1
投票
使用 C++20,当类型默认可构造且可复制时,您可以使用 now-constexpr

fill

 函数(
现场示例)直接为此创建一个帮助器:

#include <array> #include <concepts> #include <cstddef> template<std::size_t N, std::semiregular T> constexpr auto array_repeat(const T& value) -> std::array<T, N> { std::array<T, N> ret; ret.fill(value); return ret; } int main() { constexpr auto a = array_repeat<3>(11); static_assert(a == std::array<int, 3>{11, 11, 11}); }
这可能会降低效率,但这是否是一个问题取决于您。

© www.soinside.com 2019 - 2024. All rights reserved.