Index: include/experimental/array =================================================================== --- include/experimental/array +++ include/experimental/array @@ -0,0 +1,97 @@ +// -*- C++ -*- +//===------------------------------- array -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL_ARRAY +#define _LIBCPP_EXPERIMENTAL_ARRAY + +/* + experimental/array synopsis + +#include + +namespace std { +namespace experimental { +inline namespace fundamentals_v2 { + + // [container.array.creation], Array creation functions + template + constexpr array make_array(Types&&... t); + template + constexpr array, N> to_array(T (&a)[N]); + +} // namespace fundamentals_v2 +} // namespace experimental +} // namespace std + +*/ + +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 11 + +#include +#include +#include +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_LFTS_V2 + +template +struct __make_array_value_type { + using type = _D_Ty; +}; + +template +struct __make_array_value_type : common_type<_Types...> { + static_assert(sizeof...(_Types) > 0, + "An element type must be specified if there are no given values."); + + template + struct __is_ref_wrapper : false_type { }; + template + struct __is_ref_wrapper> : true_type { }; + static_assert(!disjunction_v<__is_ref_wrapper>...>, + "An element type must be specified if any of the given values " + "are reference_wrappers."); +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +array::type, sizeof...(_Types)> +make_array(_Types &&... __ts) { + return {{forward<_Types>(__ts)...}}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +array, _Num> +__to_array_impl(_Tp (&__a)[_Num], index_sequence<_Is...>) { + return {{__a[_Is]...}}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_CONSTEXPR +auto to_array(_Tp (&__a)[_Num]) -> decltype(__to_array_impl(__a, {})) { + return __to_array_impl(__a, make_index_sequence<_Num>{});; +} + +_LIBCPP_END_NAMESPACE_LFTS_V2 + +#endif // _LIBCPP_STD_VER > 11 + +#endif // _LIBCPP_EXPERIMENTAL_ARRAY Index: test/std/experimental/container/array/creation/make_array.fail.cpp =================================================================== --- test/std/experimental/container/array/creation/make_array.fail.cpp +++ test/std/experimental/container/array/creation/make_array.fail.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// + +// UNSUPPORTED: c++98, c++03, c++11 + +// +#include +#include + +static int i = 0; + +int main() { + using std::experimental::make_array; + + // expected-error@experimental/array:* {{static_assert failed}} + auto a = make_array(); // expected-error {{no matching function}} + + // expected-error@experimental/array:* {{static_assert failed}} + auto b = make_array(0, std::reference_wrapper(i)); // expected-error {{no matching function}} +} Index: test/std/experimental/container/array/creation/make_array.pass.cpp =================================================================== --- test/std/experimental/container/array/creation/make_array.pass.cpp +++ test/std/experimental/container/array/creation/make_array.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// + +// UNSUPPORTED: c++98, c++03, c++11 + +// +#include +#include +#include +#include + +#define CHECK_ARRAY(a, Ty, ...) \ +do { \ + static_assert(std::is_same::value, \ + #a"'s type is incorrect"); \ + if (a != Ty{{__VA_ARGS__}}) \ + assert(false && #a"'s values are incorrect"); \ +} while(0) + +#define STD_ARRAY(T, N) ::std::array + +int main() { + using std::experimental::make_array; + + // This is the example given in the specification. + { + int i = 1; int &ri = i; + auto a1 = make_array(i, ri); + auto a2 = make_array(i, ri, 42L); + auto a3 = make_array(i, ri); + auto a4 = make_array(); + + CHECK_ARRAY(a1, STD_ARRAY(int, 2), 1, 1); + CHECK_ARRAY(a2, STD_ARRAY(long, 3), 1L, 1L, 42L); + CHECK_ARRAY(a3, STD_ARRAY(long, 2), 1L, 1L); + CHECK_ARRAY(a4, STD_ARRAY(long, 0)); + } + + // Make sure that reference_wrappers can be used when an explicit element + // type is given. + { + int i = 1; + auto with_ref_wrapper = make_array(0, std::reference_wrapper(i)); + CHECK_ARRAY(with_ref_wrapper, STD_ARRAY(int, 2), 0, 1); + } + + // Make sure that it works correctly with constexpr. + { + constexpr auto a = make_array(0, 1, 2); + static_assert(std::is_same>::value + && a[0] == 0 && a[1] == 1 && a[2] == 2, + "constexpr array was made incorrectly."); + } +} Index: test/std/experimental/container/array/creation/to_array.pass.cpp =================================================================== --- test/std/experimental/container/array/creation/to_array.pass.cpp +++ test/std/experimental/container/array/creation/to_array.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// + +// UNSUPPORTED: c++98, c++03, c++11 + +// +#include +#include + +int main() { + using std::experimental::to_array; + + { + constexpr int raw[4] = {0, 1, 2, 3}; + constexpr auto a = to_array(raw); + + static_assert(std::is_same>::value, + "Incorrect type"); + static_assert(a[0] == 0 && a[1] == 1 && a[2] == 2 && a[3] == 3, + "Incorrect values"); + } + + { + struct S { char c; }; + + constexpr S raw[6] = { {'a'}, {'b'}, {'c'}, {'d'}, {'e'}, {'f'}, }; + constexpr auto a = to_array(raw); + + static_assert(std::is_same>::value, + "Incorrect type"); + static_assert(a[0].c == 'a' && + a[1].c == 'b' && + a[2].c == 'c' && + a[3].c == 'd' && + a[4].c == 'e' && + a[5].c == 'f', + "Incorrect values"); + } +}