1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | #pragma once |
17 | |
18 | #include <array> |
19 | #include <type_traits> |
20 | #include <utility> |
21 | |
22 | #include <folly/CPortability.h> |
23 | #include <folly/Traits.h> |
24 | #include <folly/Utility.h> |
25 | |
26 | namespace folly { |
27 | |
28 | namespace array_detail { |
29 | template <typename> |
30 | struct is_ref_wrapper : std::false_type {}; |
31 | template <typename T> |
32 | struct is_ref_wrapper<std::reference_wrapper<T>> : std::true_type {}; |
33 | |
34 | template <typename T> |
35 | using not_ref_wrapper = |
36 | folly::Negation<is_ref_wrapper<typename std::decay<T>::type>>; |
37 | |
38 | template <typename D, typename...> |
39 | struct return_type_helper { |
40 | using type = D; |
41 | }; |
42 | template <typename... TList> |
43 | struct return_type_helper<void, TList...> { |
44 | static_assert( |
45 | folly::Conjunction<not_ref_wrapper<TList>...>::value, |
46 | "TList cannot contain reference_wrappers when D is void" ); |
47 | using type = typename std::common_type<TList...>::type; |
48 | }; |
49 | |
50 | template <typename D, typename... TList> |
51 | using return_type = std:: |
52 | array<typename return_type_helper<D, TList...>::type, sizeof...(TList)>; |
53 | } // namespace array_detail |
54 | |
55 | template <typename D = void, typename... TList> |
56 | constexpr array_detail::return_type<D, TList...> make_array(TList&&... t) { |
57 | using value_type = |
58 | typename array_detail::return_type_helper<D, TList...>::type; |
59 | return {{static_cast<value_type>(std::forward<TList>(t))...}}; |
60 | } |
61 | |
62 | namespace array_detail { |
63 | template <typename MakeItem, std::size_t... Index> |
64 | FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN constexpr auto make_array_with( |
65 | MakeItem const& make, |
66 | index_sequence<Index...>) { |
67 | return std::array<decltype(make(0)), sizeof...(Index)>{{make(Index)...}}; |
68 | } |
69 | } // namespace array_detail |
70 | |
71 | // make_array_with |
72 | // |
73 | // Constructs a std::array<..., Size> with elements m(i) for i in [0, Size). |
74 | template <std::size_t Size, typename MakeItem> |
75 | constexpr auto make_array_with(MakeItem const& make) { |
76 | return array_detail::make_array_with(make, make_index_sequence<Size>{}); |
77 | } |
78 | |
79 | } // namespace folly |
80 | |