proxygen
Iterator.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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 #pragma once
18 
19 #include <functional>
20 #include <iterator>
21 #include <memory>
22 #include <tuple>
23 #include <type_traits>
24 #include <utility>
25 
26 #include <folly/Utility.h>
28 
29 namespace folly {
30 
43 template <typename... Args>
44 struct emplace_args : public std::tuple<std::decay_t<Args>...> {
45  using storage_type = std::tuple<std::decay_t<Args>...>;
46  using storage_type::storage_type;
47 };
48 
91 template <typename... Args>
93  noexcept(emplace_args<Args...>(std::forward<Args>(args)...))) {
94  return emplace_args<Args...>(std::forward<Args>(args)...);
95 }
96 
97 namespace detail {
98 template <typename Arg>
99 decltype(auto) unwrap_emplace_arg(Arg&& arg) noexcept {
100  return std::forward<Arg>(arg);
101 }
102 template <typename Arg>
103 decltype(auto) unwrap_emplace_arg(std::reference_wrapper<Arg> arg) noexcept {
104  return arg.get();
105 }
106 template <typename Arg>
107 decltype(auto) unwrap_emplace_arg(
109  return std::move(arg).get();
110 }
111 } // namespace detail
112 
125 template <size_t I, typename... Args>
126 decltype(auto) get_emplace_arg(emplace_args<Args...>&& args) noexcept {
127  using Out = std::tuple<Args...>;
129  std::forward<std::tuple_element_t<I, Out>>(std::get<I>(args)));
130 }
131 template <size_t I, typename... Args>
132 decltype(auto) get_emplace_arg(emplace_args<Args...>& args) noexcept {
133  return detail::unwrap_emplace_arg(std::get<I>(args));
134 }
135 template <size_t I, typename... Args>
136 decltype(auto) get_emplace_arg(const emplace_args<Args...>& args) noexcept {
137  return detail::unwrap_emplace_arg(std::get<I>(args));
138 }
139 template <size_t I, typename Args>
140 decltype(auto) get_emplace_arg(Args&& args) noexcept {
141  return std::get<I>(std::move(args));
142 }
143 template <size_t I, typename Args>
144 decltype(auto) get_emplace_arg(Args& args) noexcept {
145  return std::get<I>(args);
146 }
147 template <size_t I, typename Args>
148 decltype(auto) get_emplace_arg(const Args& args) noexcept {
149  return std::get<I>(args);
150 }
151 
152 namespace detail {
156 template <typename Container>
157 struct Emplace {
158  Emplace(Container& c, typename Container::iterator i)
159  : container(std::addressof(c)), iter(std::move(i)) {}
160  template <typename... Args>
161  void emplace(Args&&... args) {
162  iter = container->emplace(iter, std::forward<Args>(args)...);
163  ++iter;
164  }
165  Container* container;
166  typename Container::iterator iter;
167 };
168 
172 template <typename Container>
173 struct EmplaceHint {
174  EmplaceHint(Container& c, typename Container::iterator i)
175  : container(std::addressof(c)), iter(std::move(i)) {}
176  template <typename... Args>
177  void emplace(Args&&... args) {
178  iter = container->emplace_hint(iter, std::forward<Args>(args)...);
179  ++iter;
180  }
181  Container* container;
182  typename Container::iterator iter;
183 };
184 
188 template <typename Container>
189 struct EmplaceFront {
190  explicit EmplaceFront(Container& c) : container(std::addressof(c)) {}
191  template <typename... Args>
192  void emplace(Args&&... args) {
193  container->emplace_front(std::forward<Args>(args)...);
194  }
195  Container* container;
196 };
197 
201 template <typename Container>
202 struct EmplaceBack {
203  explicit EmplaceBack(Container& c) : container(std::addressof(c)) {}
204  template <typename... Args>
205  void emplace(Args&&... args) {
206  container->emplace_back(std::forward<Args>(args)...);
207  }
208  Container* container;
209 };
210 
217 template <typename Derived, typename EmplaceImpl, bool implicit_unpack>
219 
224 template <typename Derived, typename EmplaceImpl>
225 class emplace_iterator_base<Derived, EmplaceImpl, false>
226  : protected EmplaceImpl /* protected implementation inheritance */ {
227  public:
228  // Iterator traits.
229  using iterator_category = std::output_iterator_tag;
230  using value_type = void;
231  using difference_type = void;
232  using pointer = void;
233  using reference = void;
234  using container_type =
235  std::remove_reference_t<decltype(*EmplaceImpl::container)>;
236 
237  using EmplaceImpl::EmplaceImpl;
238 
243  template <typename T>
244  Derived& operator=(T&& arg) {
245  this->emplace(std::forward<T>(arg));
246  return static_cast<Derived&>(*this);
247  }
248 
253  template <typename... Args>
255  return unpackAndEmplace(args, index_sequence_for<Args...>{});
256  }
257  template <typename... Args>
258  Derived& operator=(const emplace_args<Args...>& args) {
259  return unpackAndEmplace(args, index_sequence_for<Args...>{});
260  }
261  template <typename... Args>
262  Derived& operator=(emplace_args<Args...>&& args) {
263  return unpackAndEmplace(std::move(args), index_sequence_for<Args...>{});
264  }
265 
266  // No-ops.
267  Derived& operator*() {
268  return static_cast<Derived&>(*this);
269  }
270  Derived& operator++() {
271  return static_cast<Derived&>(*this);
272  }
273  Derived& operator++(int) {
274  return static_cast<Derived&>(*this);
275  }
276 
277  // We need all of these explicit defaults because the custom operator=
278  // overloads disable implicit generation of these functions.
281  emplace_iterator_base& operator=(emplace_iterator_base&) = default;
282  emplace_iterator_base& operator=(const emplace_iterator_base&) = default;
283  emplace_iterator_base& operator=(emplace_iterator_base&&) noexcept = default;
284 
285  protected:
286  template <typename Args, std::size_t... I>
288  this->emplace(get_emplace_arg<I>(args)...);
289  return static_cast<Derived&>(*this);
290  }
291  template <typename Args, std::size_t... I>
292  Derived& unpackAndEmplace(const Args& args, index_sequence<I...>) {
293  this->emplace(get_emplace_arg<I>(args)...);
294  return static_cast<Derived&>(*this);
295  }
296  template <typename Args, std::size_t... I>
298  this->emplace(get_emplace_arg<I>(std::move(args))...);
299  return static_cast<Derived&>(*this);
300  }
301 };
302 
310 template <typename Derived, typename EmplaceImpl>
311 class emplace_iterator_base<Derived, EmplaceImpl, true>
312  : public emplace_iterator_base<Derived, EmplaceImpl, false> {
313  private:
315 
316  public:
317  using Base::Base;
318  using Base::operator=;
319 
324  template <typename... Args>
325  Derived& operator=(std::pair<Args...>& args) {
326  return this->unpackAndEmplace(args, index_sequence_for<Args...>{});
327  }
328  template <typename... Args>
329  Derived& operator=(const std::pair<Args...>& args) {
330  return this->unpackAndEmplace(args, index_sequence_for<Args...>{});
331  }
332  template <typename... Args>
333  Derived& operator=(std::pair<Args...>&& args) {
334  return this->unpackAndEmplace(
336  }
337 
342  template <typename... Args>
343  Derived& operator=(std::tuple<Args...>& args) {
344  return this->unpackAndEmplace(args, index_sequence_for<Args...>{});
345  }
346  template <typename... Args>
347  Derived& operator=(const std::tuple<Args...>& args) {
348  return this->unpackAndEmplace(args, index_sequence_for<Args...>{});
349  }
350  template <typename... Args>
351  Derived& operator=(std::tuple<Args...>&& args) {
352  return this->unpackAndEmplace(
354  }
355 
356  // We need all of these explicit defaults because the custom operator=
357  // overloads disable implicit generation of these functions.
360  emplace_iterator_base& operator=(emplace_iterator_base&) = default;
361  emplace_iterator_base& operator=(const emplace_iterator_base&) = default;
362  emplace_iterator_base& operator=(emplace_iterator_base&&) noexcept = default;
363 };
364 
374 template <
375  template <typename> class EmplaceImplT,
376  typename Container,
377  bool implicit_unpack>
379  : public emplace_iterator_base<
380  emplace_iterator_impl<EmplaceImplT, Container, implicit_unpack>,
381  EmplaceImplT<Container>,
382  implicit_unpack> {
383  private:
384  using Base = emplace_iterator_base<
386  EmplaceImplT<Container>,
387  implicit_unpack>;
388 
389  public:
390  using Base::Base;
391  using Base::operator=;
392 
393  // We need all of these explicit defaults because the custom operator=
394  // overloads disable implicit generation of these functions.
395  emplace_iterator_impl(const emplace_iterator_impl&) = default;
396  emplace_iterator_impl(emplace_iterator_impl&&) noexcept = default;
397  emplace_iterator_impl& operator=(emplace_iterator_impl&) = default;
398  emplace_iterator_impl& operator=(const emplace_iterator_impl&) = default;
399  emplace_iterator_impl& operator=(emplace_iterator_impl&&) noexcept = default;
400 };
401 } // namespace detail
402 
407 template <typename Container, bool implicit_unpack = true>
408 using emplace_iterator =
409  detail::emplace_iterator_impl<detail::Emplace, Container, implicit_unpack>;
410 
415 template <typename Container, bool implicit_unpack = true>
417  emplace_iterator_impl<detail::EmplaceHint, Container, implicit_unpack>;
418 
423 template <typename Container, bool implicit_unpack = true>
425  emplace_iterator_impl<detail::EmplaceFront, Container, implicit_unpack>;
426 
431 template <typename Container, bool implicit_unpack = true>
433  emplace_iterator_impl<detail::EmplaceBack, Container, implicit_unpack>;
434 
444 template <bool implicit_unpack = true, typename Container>
445 emplace_iterator<Container, implicit_unpack> emplacer(
446  Container& c,
447  typename Container::iterator i) {
449 }
450 
460 template <bool implicit_unpack = true, typename Container>
462  Container& c,
463  typename Container::iterator i) {
465 }
466 
476 template <bool implicit_unpack = true, typename Container>
478  Container& c) {
480 }
481 
491 template <bool implicit_unpack = true, typename Container>
494 }
495 } // namespace folly
Container * container
Definition: Iterator.h:165
make_index_sequence< sizeof...(T)> index_sequence_for
Definition: Utility.h:211
Derived & operator=(const emplace_args< Args... > &args)
Definition: Iterator.h:258
emplace_iterator< Container, implicit_unpack > emplacer(Container &c, typename Container::iterator i)
Definition: Iterator.h:445
Derived & unpackAndEmplace(Args &&args, index_sequence< I... >)
Definition: Iterator.h:297
void emplace(Args &&...args)
Definition: Iterator.h:161
front_emplace_iterator< Container, implicit_unpack > front_emplacer(Container &c)
Definition: Iterator.h:477
Derived & operator=(emplace_args< Args... > &args)
Definition: Iterator.h:254
EmplaceHint(Container &c, typename Container::iterator i)
Definition: Iterator.h:174
decltype(auto) unwrap_emplace_arg(folly::rvalue_reference_wrapper< Arg > arg) noexcept
Definition: Iterator.h:107
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
back_emplace_iterator< Container, implicit_unpack > back_emplacer(Container &c)
Definition: Iterator.h:492
folly::std T
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
Derived & unpackAndEmplace(const Args &args, index_sequence< I... >)
Definition: Iterator.h:292
hint_emplace_iterator< Container, implicit_unpack > hint_emplacer(Container &c, typename Container::iterator i)
Definition: Iterator.h:461
Derived & operator=(const std::tuple< Args... > &args)
Definition: Iterator.h:347
Container::iterator iter
Definition: Iterator.h:182
EmplaceFront(Container &c)
Definition: Iterator.h:190
std::tuple< std::decay_t< Args >... > storage_type
Definition: Iterator.h:45
Derived & operator=(const std::pair< Args... > &args)
Definition: Iterator.h:329
decltype(auto) get_emplace_arg(emplace_args< Args... > &&args) noexcept
Definition: Iterator.h:126
decltype(auto) unwrap_emplace_arg(Arg &&arg) noexcept
Definition: Iterator.h:99
void emplace(Args &&...args)
Definition: Iterator.h:205
AtomicCounter< T, DeterministicAtomic > Base
emplace_args< Args... > make_emplace_args(Args &&...args) noexcept(noexcept(emplace_args< Args... >(std::forward< Args >(args)...)))
Definition: Iterator.h:92
Emplace(Container &c, typename Container::iterator i)
Definition: Iterator.h:158
Derived & operator=(emplace_args< Args... > &&args)
Definition: Iterator.h:262
void emplace(Args &&...args)
Definition: Iterator.h:177
const
Definition: upload.py:398
EmplaceBack(Container &c)
Definition: Iterator.h:203
void emplace(Args &&...args)
Definition: Iterator.h:192
std::remove_reference_t< decltype(*EmplaceImpl::container)> container_type
Definition: Iterator.h:235
default
Definition: upload.py:394
Derived & unpackAndEmplace(Args &args, index_sequence< I... >)
Definition: Iterator.h:287
char c
Derived & operator=(std::tuple< Args... > &&args)
Definition: Iterator.h:351
Container::iterator iter
Definition: Iterator.h:166