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;
+}