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

ein*_*ica 6 c++ arrays stdarray

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

std::array a{1, 4, 9};
Run Code Online (Sandbox Code Playgroud)

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

std::array<int, 3> a{11};
// a == std::array<int, 3>{11, 11, 11};
Run Code Online (Sandbox Code Playgroud)

因此,我们如何构造一个仅给定重复值的数组?

编辑:我正在寻找一种解决方案,它甚至适用于不可默认构造的元素类型;因此,通过默认构造数组然后填充它的解决方案不是我所追求的 - 尽管事实上这适用于int(如示例中所示)的情况。

ein*_*ica 7

我们可以编写一个适当的命名构造函数来实现这一点

然而,实现有点笨拙,因为我们需要使用在 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>());
}
Run Code Online (Sandbox Code Playgroud)

看到这个工作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>());
}
Run Code Online (Sandbox Code Playgroud)

GodBolt

笔记:

  • 这个解决方案有点类似于 Jared Hoberock 的tuple_repeat,他的 C++11 元组实用程序的一部分。
  • 感谢@Caleth 和@LF 指出array_repeat_impl.