1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 
8 #include <array>
9 #include <type_traits>
10 #include <utility>
11 
12 #include <folly/Traits.h>
13 #include <folly/Utility.h>
14 
15 namespace folly {
16 
17 namespace array_detail {
18 template <typename>
19 struct is_ref_wrapper : std::false_type {};
20 template <typename T>
21 struct is_ref_wrapper<std::reference_wrapper<T>> : std::true_type {};
22 
23 template <typename T>
24 using not_ref_wrapper =
25     folly::Negation<is_ref_wrapper<typename std::decay<T>::type>>;
26 
27 template <typename D, typename...>
28 struct return_type_helper {
29   using type = D;
30 };
31 template <typename... TList>
32 struct return_type_helper<void, TList...> {
33   static_assert(
34       folly::Conjunction<not_ref_wrapper<TList>...>::value,
35       "TList cannot contain reference_wrappers when D is void");
36   using type = typename std::common_type<TList...>::type;
37 };
38 
39 template <typename D, typename... TList>
40 using return_type = std::
41     array<typename return_type_helper<D, TList...>::type, sizeof...(TList)>;
42 } // namespace array_detail
43 
44 template <typename D = void, typename... TList>
45 constexpr array_detail::return_type<D, TList...> make_array(TList&&... t) {
46   using value_type =
47       typename array_detail::return_type_helper<D, TList...>::type;
48   return {{static_cast<value_type>(std::forward<TList>(t))...}};
49 }
50 
51 namespace array_detail {
52 template <typename MakeItem, std::size_t... Index>
53 inline constexpr auto make_array_with(
54     MakeItem const& make,
55     folly::index_sequence<Index...>)
56       -> std::array<decltype(make(0)), sizeof...(Index)> {
57   return std::array<decltype(make(0)), sizeof...(Index)>{{make(Index)...}};
58 }
59 } // namespace array_detail
60 
61 //  make_array_with
62 //
63 //  Constructs a std::array<..., Size> with elements m(i) for i in [0, Size).
64 template <std::size_t Size, typename MakeItem>
65 constexpr auto make_array_with(MakeItem const& make)
66     -> decltype(array_detail::make_array_with(
67           make,
68           folly::make_index_sequence<Size>{})) {
69   return array_detail::make_array_with(
70       make,
71       folly::make_index_sequence<Size>{});
72 }
73 
74 } // namespace folly
75