Index: libcxx/include/array =================================================================== --- libcxx/include/array +++ libcxx/include/array @@ -479,6 +479,44 @@ #endif // !_LIBCPP_CXX03_LANG +#if _LIBCPP_VERSION > 17 + +template +_LIBCPP_CONSTEXPR array, __n> +__to_array_impl(_Tp (&__arr)[__n], index_sequence<__i...>) +{ + return {{ __arr[__i]... }}; +} + +template +_LIBCPP_CONSTEXPR array, __n> +__to_array_impl(_Tp (&&__arr)[__n], index_sequence<__i...>) +{ + return {{ _VSTD::move(__arr[__i])... }}; +} + +template +_LIBCPP_CONSTEXPR typename enable_if< + !is_array<_Tp>::value && is_constructible<_Tp, _Tp&>::value, + array, __n> +>::type +to_array(_Tp (&__arr)[__n]) +{ + return __to_array_impl(__arr, _VSTD::make_index_sequence<__n>()); +} + +template +_LIBCPP_CONSTEXPR typename enable_if< + !is_array<_Tp>::value && is_move_constructible<_Tp>::value, + array, __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 + +// + +#include +#include + +#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); + ASSERT_SAME_TYPE(decltype(std::to_array({1, 2, 3})), std::array); + ASSERT_SAME_TYPE(decltype(std::to_array({1, 2, 3})), std::array); + ASSERT_SAME_TYPE(decltype(std::to_array(a)), std::array); + ASSERT_SAME_TYPE(decltype(std::to_array({{3, .3}})), std::array); + ASSERT_SAME_TYPE(decltype(std::to_array((int[]){1, 2, 3})), std::array); + + { + MoveOnly carr[] = {MoveOnly(1), MoveOnly(2), MoveOnly(3), MoveOnly(4)}; + std::array 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 arr = std::to_array(carr); + for (std::size_t i = 0; i < 4; ++i) + assert(arr[i].v == carr[i].v); + } + + { + constexpr std::array arr = std::to_array({1, 2, 3}); + static_assert(arr[0] == 1); + static_assert(arr[1] == 2); + static_assert(arr[2] == 3); + } + + return 0; +}