std::to_array() function
- od C++20
// (1) Lvalue reference argument verison
template<class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N]);
// (2) Rvalue reference argument verison
template<class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&&a)[N]);
Creates a std::array
from the one dimensional built-in array a
.
The elements of the std::array
are copy-initialized from the corresponding element of a
.
Copying or moving multidimensional built-in array is not supported.
- (1) For every
i
in a range [ 0; N ), copy-initializes result's correspond element witha[i]
. This overload is ill-formed whenstd::is_constructible_v<T, T&>
isfalse
. - (2) For every
i
in a range [ 0; N ), move-initializes result's correspond element withstd::move(a[i])
. This overload is ill-formed whenstd::is_move_constructible_v<T>
isfalse
.
Both overloads are ill-formed when std::is_array_v<T>
is true
.
Parameters
a
- the built-in array to be converted tostd::array
Type requirements
-
T
must meet the requirements of CopyConstructible for overload (1) -
T
must meet the requirements of MoveConstructible for overload (2)
Return value
- (1)
std::array<std::remove_cv_t<T>, N>{ a[0], ..., a[N - 1] }
- (2)
std::array<std::remove_cv_t<T>, N>{ std::move(a[0]), ..., std::move(a[N - 1]) }
Complexity
Linear in the size of the built-in array.
Notes
There are some occasions where class template argument deduction
ofstd::array
cannot be used while to_array
being available:
to_array
can be used when the element type of thestd::array
is manually specified and the length is deduced, which is preferable when implicit conversion is wanted.to_array
can copy a string literal, while class template argument deduction constructs astd::array
of a single pointer to its first character.
std::to_array<long>({3, 4}); // OK: implicit conversion
// std::array<long>{3, 4}; // error: too few template arguments
std::to_array("foo"); // creates std::array<char, 4>{ 'f', 'o', 'o', '\0' }
std::array{"foo"}; // creates std::array<const char*, 1>{ +"foo" }
Feature testing macro: __cpp_lib_to_array
Possible implementations
Overload (1)
namespace detail {
template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
return { {a[I]...} };
}
}
template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
return detail::to_array_impl(a, std::make_index_sequence<N>{});
}
Overload (2)
namespace detail {
template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
to_array_impl(T (&&a)[N], std::index_sequence<I...>)
{
return { {std::move(a[I])...} };
}
}
template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&&a)[N])
{
return detail::to_array_impl(std::move(a), std::make_index_sequence<N>{});
}
Example
#include <type_traits>
#include <utility>
#include <array>
#include <memory>
int main()
{
// copies a string literal
auto a1 = std::to_array("foo");
static_assert(a1.size() == 4);
// deduces both element type and length
auto a2 = std::to_array({ 0, 2, 1, 3 });
static_assert(std::is_same_v<decltype(a2), std::array<int, 4>>);
// deduces length with element type specified
// implicit conversion happens
auto a3 = std::to_array<long>({ 0, 1, 3 });
static_assert(std::is_same_v<decltype(a3), std::array<long, 3>>);
auto a4 = std::to_array<std::pair<int, float>>(
{ { 3, .0f }, { 4, .1f }, { 4, .1e23f } });
static_assert(a4.size() == 3);
// creates a non-copyable std::array
auto a5 = std::to_array({ std::make_unique<int>(3) });
static_assert(a5.size() == 1);
// error: copying multidimensional arrays is not supported
// char s[2][6] = { "nice", "thing" };
// auto a6 = std::to_array(s);
}
(no output)
Hover to see the original license.