std::array
can be constructed (at compile time with newer C++ versions) with specific values, eg
std::array a{1, 4, 9};
however - it does not have a constructor, or a standard-library named constructor idiom, taking a single value and replicating it. ie we don't have:
std::array<int, 3> a{11};
// a == std::array<int, 3>{11, 11, 11};
How can we, therefore, construct an array given just the value to repeat?
Edit: I'm looking for a solution which would work even for element types which are not default constructible; so, a solution going through default-constructing the array, then filling it, is not what I'm after - despite the fact that this will work for the case of int
(like in the example).
We can write an appropriate named constructor idiom to achieve this
The implementation is a bit clunky, however, as we need to use the "indices trick" that takes a lot of boilerplate in C++11, so let's assume 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>());
}
See this working on GodBolt .
If you can compile your code C++20, you can drop the dependency on make_array
and write:
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>());
}
Notes:
tuple_repeat
, part of his tuple utilities for C++11 .array_repeat_impl
.With C++20, you can make a helper for this straightforwardly when the type is default-constructible and copyable by using the now-constexpr fill
function ( live example ):
#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});
}
This could potentially be less efficient, but whether that's a problem is up to you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.