diff --git a/libcxx/include/array b/libcxx/include/array --- a/libcxx/include/array +++ b/libcxx/include/array @@ -479,6 +479,40 @@ #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 && is_copy_constructible_v<_Tp>>> +_LIBCPP_CONSTEXPR array, __n> +to_array(_Tp (&__arr)[__n]) +{ + return __to_array_impl(__arr, _VSTD::make_index_sequence<__n>()); +} + +template && is_move_constructible_v<_Tp>>> +_LIBCPP_CONSTEXPR array, __n> +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 diff --git a/libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp b/libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/array.creation/to_array.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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" +#include "CopyOnly.h" +#include "MoveOnly.h" + +struct Foo { int a; double b; }; + +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 (int i = 1; i < 5; ++i) + assert(arr[i - 1].get() == i && carr[i - 1] == 0); + } + + { + 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].get() == carr[i].get()); + } + + { + 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; +} diff --git a/libcxx/test/support/CopyOnly.h b/libcxx/test/support/CopyOnly.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/CopyOnly.h @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef COPYONLY_H +#define COPYONLY_H + +#include "test_macros.h" + +#if TEST_STD_VER >= 11 + +#include +#include + +class CopyOnly +{ + CopyOnly(CopyOnly&& x); + CopyOnly& operator=(CopyOnly&& x); + + int data_; +public: + CopyOnly(int data = 1) : data_(data) {} + + CopyOnly(CopyOnly const& x) + : data_(x.data_) {} + + CopyOnly& operator=(CopyOnly const& x) + { data_ = x.data_; return *this;} + + int get() const {return data_;} + + bool operator==(const CopyOnly& x) const {return data_ == x.data_;} + bool operator< (const CopyOnly& x) const {return data_ < x.data_;} + CopyOnly operator+(const CopyOnly& x) const { return CopyOnly{data_ + x.data_}; } + CopyOnly operator*(const CopyOnly& x) const { return CopyOnly{data_ * x.data_}; } +}; + +namespace std { + +template <> +struct hash +{ + typedef CopyOnly argument_type; + typedef size_t result_type; + std::size_t operator()(const CopyOnly& x) const {return x.get();} +}; + +} + +#endif // TEST_STD_VER >= 11 + +#endif // COPYONLY_H