proxygen
Core-inl.h
Go to the documentation of this file.
1 /*
2  * Copyright 2014-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 
17 #ifndef FOLLY_GEN_CORE_H_
18 #error This file may only be included from folly/gen/Core.h
19 #endif
20 
21 #include <type_traits>
22 #include <utility>
23 
24 #include <folly/Portability.h>
25 
26 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
28 FOLLY_GNU_DISABLE_WARNING("-Wshadow")
29 
30 namespace folly {
31 namespace gen {
32 
40 template <class Candidate, class Expected>
42  static constexpr bool value = false;
43 };
44 
45 template <class Candidate, class ExpectedReturn, class... ArgTypes>
46 class IsCompatibleSignature<Candidate, ExpectedReturn(ArgTypes...)> {
47  template <
48  class F,
49  class ActualReturn =
50  decltype(std::declval<F>()(std::declval<ArgTypes>()...)),
52  static constexpr bool testArgs(int*) {
53  return good;
54  }
55 
56  template <class F>
57  static constexpr bool testArgs(...) {
58  return false;
59  }
60 
61  public:
62  static constexpr bool value = testArgs<Candidate>(nullptr);
63 };
64 
69 template <class Self>
70 struct FBounded {
71  const Self& self() const {
72  return *static_cast<const Self*>(this);
73  }
74 
75  Self& self() {
76  return *static_cast<Self*>(this);
77  }
78 };
79 
85 template <class Self>
86 class Operator : public FBounded<Self> {
87  public:
92  template <class Source, class Value, class ResultGen = void>
93  ResultGen compose(const GenImpl<Value, Source>& source) const;
94 
95  protected:
96  Operator() = default;
97  Operator(Operator&&) noexcept = default;
98  Operator(const Operator&) = default;
99  Operator& operator=(Operator&&) noexcept = default;
100  Operator& operator=(const Operator&) = default;
101 };
102 
107 template <
108  class Left,
109  class Right,
110  class Composed = detail::Composed<Left, Right>>
111 Composed operator|(const Operator<Left>& left, const Operator<Right>& right) {
112  return Composed(left.self(), right.self());
113 }
114 
115 template <
116  class Left,
117  class Right,
118  class Composed = detail::Composed<Left, Right>>
119 Composed operator|(const Operator<Left>& left, Operator<Right>&& right) {
120  return Composed(left.self(), std::move(right.self()));
121 }
122 
123 template <
124  class Left,
125  class Right,
126  class Composed = detail::Composed<Left, Right>>
127 Composed operator|(Operator<Left>&& left, const Operator<Right>& right) {
128  return Composed(std::move(left.self()), right.self());
129 }
130 
131 template <
132  class Left,
133  class Right,
134  class Composed = detail::Composed<Left, Right>>
135 Composed operator|(Operator<Left>&& left, Operator<Right>&& right) {
136  return Composed(std::move(left.self()), std::move(right.self()));
137 }
138 
145 template <class Value, class Self>
146 class GenImpl : public FBounded<Self> {
147  protected:
148  // To prevent slicing
149  GenImpl() = default;
150  GenImpl(GenImpl&&) = default;
151  GenImpl(const GenImpl&) = default;
152  GenImpl& operator=(GenImpl&&) = default;
153  GenImpl& operator=(const GenImpl&) = default;
154 
155  public:
156  typedef Value ValueType;
158 
166  template <class Handler>
167  bool apply(Handler&& handler) const;
168 
172  template <class Body>
173  void foreach(Body&& body) const {
174  this->self().apply([&](Value value) -> bool {
175  static_assert(!infinite, "Cannot call foreach on infinite GenImpl");
176  body(std::forward<Value>(value));
177  return true;
178  });
179  }
180 
181  // Child classes should override if the sequence generated is *definitely*
182  // infinite. 'infinite' may be false_type for some infinite sequences
183  // (due the the Halting Problem).
184  //
185  // In general, almost all sources are finite (only seq(n) produces an infinite
186  // source), almost all operators keep the finiteness of the source (only cycle
187  // makes an infinite generator from a finite one, only until and take make a
188  // finite generator from an infinite one, and concat needs both the inner and
189  // outer generators to be finite to make a finite one), and most sinks
190  // cannot accept and infinite generators (first being the expection).
191  static constexpr bool infinite = false;
192 };
193 
194 template <
195  class LeftValue,
196  class Left,
197  class RightValue,
198  class Right,
200 Chain operator+(
201  const GenImpl<LeftValue, Left>& left,
202  const GenImpl<RightValue, Right>& right) {
203  static_assert(
205  "Generators may ony be combined if Values are the exact same type.");
206  return Chain(left.self(), right.self());
207 }
208 
209 template <
210  class LeftValue,
211  class Left,
212  class RightValue,
213  class Right,
215 Chain operator+(
216  const GenImpl<LeftValue, Left>& left,
217  GenImpl<RightValue, Right>&& right) {
218  static_assert(
220  "Generators may ony be combined if Values are the exact same type.");
221  return Chain(left.self(), std::move(right.self()));
222 }
223 
224 template <
225  class LeftValue,
226  class Left,
227  class RightValue,
228  class Right,
230 Chain operator+(
232  const GenImpl<RightValue, Right>& right) {
233  static_assert(
235  "Generators may ony be combined if Values are the exact same type.");
236  return Chain(std::move(left.self()), right.self());
237 }
238 
239 template <
240  class LeftValue,
241  class Left,
242  class RightValue,
243  class Right,
245 Chain operator+(
247  GenImpl<RightValue, Right>&& right) {
248  static_assert(
250  "Generators may ony be combined if Values are the exact same type.");
251  return Chain(std::move(left.self()), std::move(right.self()));
252 }
253 
258 template <class Value, class Gen, class Handler>
259 typename std::enable_if<
261 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
262  static_assert(
263  !Gen::infinite, "Cannot pull all values from an infinite sequence.");
264  gen.self().foreach(std::forward<Handler>(handler));
265 }
266 
271 template <class Value, class Gen, class Handler>
272 typename std::
274  operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
275  return gen.self().apply(std::forward<Handler>(handler));
276 }
277 
283 template <class Value, class Gen, class Op>
285  -> decltype(op.self().compose(gen.self())) {
286  return op.self().compose(gen.self());
287 }
288 
289 template <class Value, class Gen, class Op>
291  -> decltype(op.self().compose(std::move(gen.self()))) {
292  return op.self().compose(std::move(gen.self()));
293 }
294 
295 namespace detail {
296 
308 template <class First, class Second>
309 class Composed : public Operator<Composed<First, Second>> {
311  Second second_;
312 
313  public:
314  Composed() = default;
315 
316  Composed(First first, Second second)
317  : first_(std::move(first)), second_(std::move(second)) {}
318 
319  template <
320  class Source,
321  class Value,
322  class FirstRet =
323  decltype(std::declval<First>().compose(std::declval<Source>())),
324  class SecondRet =
325  decltype(std::declval<Second>().compose(std::declval<FirstRet>()))>
326  SecondRet compose(const GenImpl<Value, Source>& source) const {
327  return second_.compose(first_.compose(source.self()));
328  }
329 
330  template <
331  class Source,
332  class Value,
333  class FirstRet =
334  decltype(std::declval<First>().compose(std::declval<Source>())),
335  class SecondRet =
336  decltype(std::declval<Second>().compose(std::declval<FirstRet>()))>
337  SecondRet compose(GenImpl<Value, Source>&& source) const {
338  return second_.compose(first_.compose(std::move(source.self())));
339  }
340 };
341 
350 template <class Value, class First, class Second>
351 class Chain : public GenImpl<Value, Chain<Value, First, Second>> {
353  Second second_;
354 
355  public:
356  explicit Chain(First first, Second second)
357  : first_(std::move(first)), second_(std::move(second)) {}
358 
359  template <class Handler>
360  bool apply(Handler&& handler) const {
361  return first_.apply(std::forward<Handler>(handler)) &&
362  second_.apply(std::forward<Handler>(handler));
363  }
364 
365  template <class Body>
366  void foreach(Body&& body) const {
367  first_.foreach(std::forward<Body>(body));
368  second_.foreach(std::forward<Body>(body));
369  }
370 
371  static constexpr bool infinite = First::infinite || Second::infinite;
372 };
373 
374 } // namespace detail
375 } // namespace gen
376 } // namespace folly
377 
#define FOLLY_GNU_DISABLE_WARNING(warningName)
Definition: Portability.h:180
#define FOLLY_POP_WARNING
Definition: Portability.h:179
#define FOLLY_PUSH_WARNING
Definition: Portability.h:178
PskType type
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
void handler(int, siginfo_t *, void *)
bool Value(const T &value, M matcher)
Optional< StorageType > compose(const GenImpl< Value, Source > &source) const
Definition: Base-inl.h:2039
auto operator|(GenImpl< Value, Gen > &&gen, const Operator< Op > &op) -> decltype(op.self().compose(std::move(gen.self())))
Definition: Core-inl.h:290
Chain(First first, Second second)
Definition: Core-inl.h:356
std::decay< Value >::type StorageType
Definition: Core-inl.h:157
SecondRet compose(GenImpl< Value, Source > &&source) const
Definition: Core-inl.h:337
static const char *const value
Definition: Conv.cpp:50
bool apply(Handler &&handler) const
Definition: Core-inl.h:360
Chain operator+(GenImpl< LeftValue, Left > &&left, GenImpl< RightValue, Right > &&right)
Definition: Core-inl.h:245
const Self & self() const
Definition: Core-inl.h:71
Composed(First first, Second second)
Definition: Core-inl.h:316
decltype(auto) constexpr apply(F &&func, Tuple &&tuple)
Definition: ApplyTuple.h:87
SecondRet compose(const GenImpl< Value, Source > &source) const
Definition: Core-inl.h:326
constexpr detail::First first
Definition: Base-inl.h:2553