We can write an appropriate named constructor idiom to achieve this. Then, your example definition would look like:
auto a = array_repeat<3>(11);
// a == std::array<int, 3>{11, 11, 11};
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>());
}
GodBolt
Notes:
- This solution is somewhat similar to Jared Hoberock's
tuple_repeat
, part of his tuple utilities for C++11.
- Thanks goes to @Caleth and @L.F. for pointing out a inappropriate forwarding in
array_repeat_impl
.
- The
array_repert()
function take rvalue references and moves from them, so it's ok to create a temporary in the argument, even if it's expensive.