Przejdź do głównej zawartości

std::to_array() function

// (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 with a[i]. This overload is ill-formed when std::is_constructible_v<T, T&> is false.
  • (2) For every i in a range [ 0; N ), move-initializes result's correspond element with std::move(a[i]). This overload is ill-formed when std::is_move_constructible_v<T> is false.

Both overloads are ill-formed when std::is_array_v<T> is true.

Parameters

  • a - the built-in array to be converted to std::array

Type requirements

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

of std::array cannot be used while to_array being available:

  • to_array can be used when the element type of the std::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 a std::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);
}
Possible output
(no output)
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::to_array() function

// (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 with a[i]. This overload is ill-formed when std::is_constructible_v<T, T&> is false.
  • (2) For every i in a range [ 0; N ), move-initializes result's correspond element with std::move(a[i]). This overload is ill-formed when std::is_move_constructible_v<T> is false.

Both overloads are ill-formed when std::is_array_v<T> is true.

Parameters

  • a - the built-in array to be converted to std::array

Type requirements

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

of std::array cannot be used while to_array being available:

  • to_array can be used when the element type of the std::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 a std::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);
}
Possible output
(no output)
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.