scnlib  0.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tuple_return.h
Go to the documentation of this file.
1 // Copyright 2017-2019 Elias Kosunen
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // This file is a part of scnlib:
16 // https://github.com/eliaskosunen/scnlib
17 
18 #ifndef SCN_DETAIL_TUPLE_RETURN_H
19 #define SCN_DETAIL_TUPLE_RETURN_H
20 
21 #include "scan.h"
22 
23 #include <functional>
24 #include <tuple>
25 
26 namespace scn {
28 
29  namespace detail {
30  // From cppreference
31  template <typename Fn,
32  typename... Args,
33  typename std::enable_if<std::is_member_pointer<
34  typename std::decay<Fn>::type>::value>::type* = nullptr,
35  int = 0>
36  constexpr auto invoke(Fn&& f, Args&&... args) noexcept(
37  noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
38  -> decltype(std::mem_fn(f)(std::forward<Args>(args)...))
39  {
40  return std::mem_fn(f)(std::forward<Args>(args)...);
41  }
42 
43  template <typename Fn,
44  typename... Args,
45  typename std::enable_if<!std::is_member_pointer<
46  typename std::decay<Fn>::type>::value>::type* = nullptr>
47  constexpr auto invoke(Fn&& f, Args&&... args) noexcept(
48  noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
49  -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...))
50  {
51  return std::forward<Fn>(f)(std::forward<Args>(args)...);
52  }
53 
54  // From Boost.mp11
55  template <typename T, T... I>
57  };
58 
59  // iseq_if_c
60  template <bool C, typename T, typename E>
62 
63  template <typename T, typename E>
64  struct iseq_if_c_impl<true, T, E> {
65  using type = T;
66  };
67 
68  template <typename T, typename E>
69  struct iseq_if_c_impl<false, T, E> {
70  using type = E;
71  };
72 
73  template <bool C, typename T, typename E>
75 
76  // iseq_identity
77  template <typename T>
78  struct iseq_identity {
79  using type = T;
80  };
81 
82  template <typename S1, typename S2>
84 
85  template <typename T, T... I, T... J>
87  integer_sequence<T, J...>> {
88  using type = integer_sequence<T, I..., (J + sizeof...(I))...>;
89  };
90 
91  template <typename T, T N>
93 
94  template <typename T, T N>
96  private:
97  static_assert(
98  N >= 0,
99  "make_integer_sequence<T, N>: N must not be negative");
100 
101  static T const M = N / 2;
102  static T const R = N % 2;
103 
104  using S1 = typename make_integer_sequence_impl<T, M>::type;
105  using S2 = typename append_integer_sequence<S1, S1>::type;
106  using S3 = typename make_integer_sequence_impl<T, R>::type;
107  using S4 = typename append_integer_sequence<S2, S3>::type;
108 
109  public:
110  using type = S4;
111  };
112 
113  template <typename T, T N>
115  : iseq_if_c<N == 0,
116  iseq_identity<integer_sequence<T>>,
117  iseq_if_c<N == 1,
118  iseq_identity<integer_sequence<T, 0>>,
119  make_integer_sequence_impl_<T, N>>> {
120  };
121 
122  // make_integer_sequence
123  template <typename T, T N>
124  using make_integer_sequence =
126 
127  // index_sequence
128  template <std::size_t... I>
129  using index_sequence = integer_sequence<std::size_t, I...>;
130 
131  // make_index_sequence
132  template <std::size_t N>
134 
135  // index_sequence_for
136  template <typename... T>
137  using index_sequence_for =
138  make_integer_sequence<std::size_t, sizeof...(T)>;
139 
140  // From cppreference
141  template <class F, class Tuple, std::size_t... I>
142  constexpr auto
143  apply_impl(F&& f, Tuple&& t, index_sequence<I...>) noexcept(
144  noexcept(detail::invoke(std::forward<F>(f),
145  std::get<I>(std::forward<Tuple>(t))...)))
146  -> decltype(detail::invoke(std::forward<F>(f),
147  std::get<I>(std::forward<Tuple>(t))...))
148  {
149  return detail::invoke(std::forward<F>(f),
150  std::get<I>(std::forward<Tuple>(t))...);
151  } // namespace detail
152 
153  template <class F, class Tuple>
154  constexpr auto apply(F&& f, Tuple&& t) noexcept(
155  noexcept(detail::apply_impl(
156  std::forward<F>(f),
157  std::forward<Tuple>(t),
158  make_index_sequence<std::tuple_size<
159  typename std::remove_reference<Tuple>::type>::value>{})))
160  -> decltype(detail::apply_impl(
161  std::forward<F>(f),
162  std::forward<Tuple>(t),
163  make_index_sequence<std::tuple_size<
164  typename std::remove_reference<Tuple>::type>::value>{}))
165  {
166  return detail::apply_impl(
167  std::forward<F>(f), std::forward<Tuple>(t),
168  make_index_sequence<std::tuple_size<
169  typename std::remove_reference<Tuple>::type>::value>{});
170  }
171  } // namespace detail
172 
173  template <typename... Args, typename Range, typename Format>
174  SCN_NODISCARD auto scan_tuple(const Range& r, Format f)
175  -> std::tuple<detail::scan_result_for_range_t<const Range&>, Args...>
176  {
178  auto scanfn = [&r, &f](Args&... a) { return ::scn::scan(r, f, a...); };
179  std::tuple<Args...> values{Args{}...};
180  auto ret = detail::apply(scanfn, values);
181  return std::tuple_cat(std::tuple<result>{std::move(ret)},
182  std::move(values));
183  }
184  template <typename... Args, typename Range, typename Format>
185  SCN_NODISCARD auto scan_tuple(Range&& r, Format f) ->
186  typename std::enable_if<
187  !std::is_reference<Range>::value,
188  std::tuple<detail::scan_result_for_range_t<Range>, Args...>>::type
189  {
191  auto scanfn = [&r, &f](Args&... a) {
192  return ::scn::scan(std::move(r), f, a...);
193  };
194  std::tuple<Args...> values{Args{}...};
195  auto ret = detail::apply(scanfn, values);
196  return std::tuple_cat(std::tuple<result>{std::move(ret)},
197  std::move(values));
198  }
199 
200  template <typename... Args, typename Range>
202  -> std::tuple<detail::scan_result_for_range_t<const Range&>, Args...>
203  {
205  auto scanfn = [&r](Args&... a) {
206  return ::scn::scan(r, default_tag, a...);
207  };
208  std::tuple<Args...> values{Args{}...};
209  auto ret = detail::apply(scanfn, values);
210  return std::tuple_cat(std::tuple<result>{std::move(ret)},
211  std::move(values));
212  }
213  template <typename... Args, typename Range>
215  typename std::enable_if<
216  !std::is_reference<Range>::value,
217  std::tuple<detail::scan_result_for_range_t<Range>, Args...>>::type
218  {
220  auto scanfn = [&r](Args&... a) {
221  return ::scn::scan(std::move(r), default_tag, a...);
222  };
223  std::tuple<Args...> values{Args{}...};
224  auto ret = detail::apply(scanfn, values);
225  return std::tuple_cat(std::tuple<result>{std::move(ret)},
226  std::move(values));
227  }
228 
230 } // namespace scn
231 
232 #endif
typename iseq_if_c_impl< C, T, E >::type iseq_if_c
Definition: tuple_return.h:74
#define SCN_END_NAMESPACE
Definition: config.h:401
typename detail::make_integer_sequence_impl< T, N >::type make_integer_sequence
Definition: tuple_return.h:125
constexpr auto apply(F &&f, Tuple &&t) noexcept(noexcept(detail::apply_impl(std::forward< F >(f), std::forward< Tuple >(t), make_index_sequence< std::tuple_size< typename std::remove_reference< Tuple >::type >::value >{}))) -> decltype(detail::apply_impl(std::forward< F >(f), std::forward< Tuple >(t), make_index_sequence< std::tuple_size< typename std::remove_reference< Tuple >::type >::value >
Definition: tuple_return.h:154
SCN_NODISCARD auto scan_tuple(const Range &r, Format f) -> std::tuple< detail::scan_result_for_range_t< const Range & >, Args...>
Definition: tuple_return.h:174
typename scan_result_for_range< Range, E >::type scan_result_for_range_t
Definition: scan.h:37
#define SCN_NODISCARD
Definition: config.h:259
make_integer_sequence< std::size_t, sizeof...(T)> index_sequence_for
Definition: tuple_return.h:138
#define SCN_BEGIN_NAMESPACE
Definition: config.h:400
auto scan(Range &&r, const Format &f, Args &...a) -> detail::scan_result_for_range_t< Range >
The most fundamental part of the scanning API.
Definition: scan.h:73
make_integer_sequence< std::size_t, N > make_index_sequence
Definition: tuple_return.h:133
auto get(const subrange< I, S, K > &s) -> decltype(_subrange_get_impl< N >::get(s))
Definition: ranges.h:1185
constexpr auto invoke(Fn &&f, Args &&...args) noexcept(noexcept(std::mem_fn(f)(std::forward< Args >(args)...))) -> decltype(std::mem_fn(f)(std::forward< Args >(args)...))
Definition: tuple_return.h:36
constexpr auto apply_impl(F &&f, Tuple &&t, index_sequence< I...>) noexcept(noexcept(detail::invoke(std::forward< F >(f), std::get< I >(std::forward< Tuple >(t))...))) -> decltype(detail::invoke(std::forward< F >(f), std::get< I >(std::forward< Tuple >(t))...))
Definition: tuple_return.h:143