scnlib  0.1.2
FormattedinputformodernC++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
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 Stream>
174  SCN_NODISCARD std::tuple<scan_result, Args...> scan(
175  Stream& s,
177  {
178  auto scanfn = [&s, &f](scan_result& r, Args&... a) -> void {
179  r = ::scn::scan(s, f, a...);
180  };
181  std::tuple<scan_result, Args...> values{scan_result{0}, Args{}...};
182  detail::apply(scanfn, values);
183  return values;
184  }
185 
186  template <typename... Args, typename Stream>
187  SCN_NODISCARD std::tuple<scan_result, Args...> scan(Stream& s,
189  {
190  auto scanfn = [&s](scan_result& r, Args&... a) -> void {
191  r = ::scn::scan(s, default_tag, a...);
192  };
193  std::tuple<scan_result, Args...> values{scan_result{0}, Args{}...};
194  detail::apply(scanfn, values);
195  return values;
196  }
197 
199 } // namespace scn
200 
201 #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:376
SCN_NODISCARD std::tuple< scan_result, Args...> scan(Stream &s, detail::default_t)
Definition: tuple_return.h:187
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
#define SCN_NODISCARD
Definition: config.h:239
make_integer_sequence< std::size_t, sizeof...(T)> index_sequence_for
Definition: tuple_return.h:138
#define SCN_BEGIN_NAMESPACE
Definition: config.h:375
SCN_BEGIN_NAMESPACE scan_result scan(Stream &s, basic_string_view< typename Stream::char_type > f, Args &...a)
Definition: scan.h:27
result< int > scan_result
Definition: result.h:178
make_integer_sequence< std::size_t, N > make_index_sequence
Definition: tuple_return.h:133
A view over a (sub)string.
Definition: string_view.h:56
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