Index: libcxx/include/array =================================================================== --- libcxx/include/array +++ libcxx/include/array @@ -479,6 +479,44 @@ #endif // !_LIBCPP_CXX03_LANG +#if _LIBCPP_VERSION > 17 + +template <class _Tp, _VSTD::size_t __n, size_t... __i> +_LIBCPP_CONSTEXPR array<remove_cv_t<_Tp>, __n> +__to_array_impl(_Tp (&__arr)[__n], index_sequence<__i...>) +{ + return {{ __arr[__i]... }}; +} + +template <class _Tp, _VSTD::size_t __n, size_t... __i> +_LIBCPP_CONSTEXPR array<remove_cv_t<_Tp>, __n> +__to_array_impl(_Tp (&&__arr)[__n], index_sequence<__i...>) +{ + return {{ _VSTD::move(__arr[__i])... }}; +} + +template <class _Tp, _VSTD::size_t __n> +_LIBCPP_CONSTEXPR typename enable_if< + !is_array<_Tp>::value && is_constructible<_Tp, _Tp&>::value, + array<remove_cv_t<_Tp>, __n> +>::type +to_array(_Tp (&__arr)[__n]) +{ + return __to_array_impl(__arr, _VSTD::make_index_sequence<__n>()); +} + +template <class _Tp, _VSTD::size_t __n> +_LIBCPP_CONSTEXPR typename enable_if< + !is_array<_Tp>::value && is_move_constructible<_Tp>::value, + array<remove_cv_t<_Tp>, __n> +>::type +to_array(_Tp (&&__arr)[__n]) +{ + return __to_array_impl(_VSTD::move(__arr), _VSTD::make_index_sequence<__n>()); +} + +#endif // _LIBCPP_VERSION > 17 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_ARRAY Index: libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <array> + +#include <array> +#include <cassert> + +#include "test_macros.h" + +struct Foo { int a; double b; }; + +struct MoveOnly +{ + int v = 0; + + MoveOnly(int v) : v(v) { } + MoveOnly(MoveOnly&& other) { v = std::move(other.v); } + MoveOnly(MoveOnly const&) { assert(false); } +}; + +struct CopyOnly +{ + int v = 0; + + CopyOnly(int v) : v(v) { } + CopyOnly(CopyOnly&&) { assert(false); } + CopyOnly(CopyOnly const& other) { v = other.v; } +}; + +int main(int, char**) +{ + int a[3] = {}; + + ASSERT_SAME_TYPE(decltype(std::to_array("foo")), std::array<char, 4>); + ASSERT_SAME_TYPE(decltype(std::to_array({1, 2, 3})), std::array<int, 3>); + ASSERT_SAME_TYPE(decltype(std::to_array<std::size_t>({1, 2, 3})), std::array<std::size_t, 3>); + ASSERT_SAME_TYPE(decltype(std::to_array(a)), std::array<int, 3>); + ASSERT_SAME_TYPE(decltype(std::to_array<Foo>({{3, .3}})), std::array<Foo, 1>); + ASSERT_SAME_TYPE(decltype(std::to_array((int[]){1, 2, 3})), std::array<int, 3>); + + { + MoveOnly carr[] = {MoveOnly(1), MoveOnly(2), MoveOnly(3), MoveOnly(4)}; + std::array<MoveOnly, 4> arr = std::to_array(std::move(carr)); + for (std::size_t i = 0; i < 4; ++i) + assert(arr[i].v == carr[i].v); + } + + { + CopyOnly carr[] = {CopyOnly(1), CopyOnly(2), CopyOnly(3), CopyOnly(4)}; + std::array<CopyOnly, 4> arr = std::to_array(carr); + for (std::size_t i = 0; i < 4; ++i) + assert(arr[i].v == carr[i].v); + } + + { + constexpr std::array<int, 3> arr = std::to_array({1, 2, 3}); + static_assert(arr[0] == 1); + static_assert(arr[1] == 2); + static_assert(arr[2] == 3); + } + + return 0; +}