2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <type_traits>
26 #include <folly/Functional.h>
31 * Argument tuple for variadic emplace/constructor calls. Stores arguments by
32 * (decayed) value. Restores original argument types with reference qualifiers
33 * and adornments at unpack time to emulate perfect forwarding.
35 * Uses inheritance instead of a type alias to std::tuple so that emplace
36 * iterators with implicit unpacking disabled can distinguish between
37 * emplace_args and std::tuple parameters.
39 * @seealso folly::make_emplace_args
40 * @seealso folly::get_emplace_arg
42 template <typename... Args>
43 struct emplace_args : public std::tuple<std::decay_t<Args>...> {
44 using storage_type = std::tuple<std::decay_t<Args>...>;
45 using storage_type::storage_type;
49 * Pack arguments in a tuple for assignment to a folly::emplace_iterator,
50 * folly::front_emplace_iterator, or folly::back_emplace_iterator. The
51 * iterator's operator= will unpack the tuple and pass the unpacked arguments
52 * to the container's emplace function, which in turn forwards the arguments to
53 * the (multi-argument) constructor of the target class.
55 * Argument tuples generated with folly::make_emplace_args will be unpacked
56 * before being passed to the container's emplace function, even for iterators
57 * where implicit_unpack is set to false (so they will not implicitly unpack
58 * std::pair or std::tuple arguments to operator=).
60 * Arguments are copied (lvalues) or moved (rvalues). To avoid copies and moves,
61 * wrap references using std::ref(), std::cref(), and folly::rref(). Beware of
62 * dangling references, especially references to temporary objects created with
65 * Note that an argument pack created with folly::make_emplace_args is different
66 * from an argument pack created with std::make_pair or std::make_tuple.
67 * Specifically, passing a std::pair&& or std::tuple&& to an emplace iterator's
68 * operator= will pass rvalue references to all fields of that tuple to the
69 * container's emplace function, while passing an emplace_args&& to operator=
70 * will cast those field references to the exact argument types as passed to
71 * folly::make_emplace_args previously. If all arguments have been wrapped by
72 * std::reference_wrappers or folly::rvalue_reference_wrappers, the result will
73 * be the same as if the container's emplace function had been called directly
74 * (perfect forwarding), with no temporary copies of the arguments.
76 * @seealso folly::rref
79 * class Widget { Widget(int, int); };
80 * std::vector<Widget> makeWidgets(const std::vector<int>& in) {
81 * std::vector<Widget> out;
85 * folly::back_emplacer(out),
86 * [](int i) { return folly::make_emplace_args(i, i); });
90 template <typename... Args>
91 emplace_args<Args...> make_emplace_args(Args&&... args) noexcept(
92 noexcept(emplace_args<Args...>(std::forward<Args>(args)...))) {
93 return emplace_args<Args...>(std::forward<Args>(args)...);
97 template <typename Arg>
98 decltype(auto) unwrap_emplace_arg(Arg&& arg) noexcept {
99 return std::forward<Arg>(arg);
101 template <typename Arg>
102 decltype(auto) unwrap_emplace_arg(std::reference_wrapper<Arg> arg) noexcept {
105 template <typename Arg>
106 decltype(auto) unwrap_emplace_arg(
107 folly::rvalue_reference_wrapper<Arg> arg) noexcept {
108 return std::move(arg).get();
113 * Getter function for unpacking a single emplace argument.
115 * Calling get_emplace_arg on an emplace_args rvalue reference results in
116 * perfect forwarding of the original input types. A special case are
117 * std::reference_wrapper and folly::rvalue_reference_wrapper objects within
118 * folly::emplace_args. These are also unwrapped so that the bare reference is
121 * std::get is not a customization point in the standard library, so the
122 * cleanest solution was to define our own getter function.
124 template <size_t I, typename... Args>
125 decltype(auto) get_emplace_arg(emplace_args<Args...>&& args) noexcept {
126 using Out = std::tuple<Args...>;
127 return detail::unwrap_emplace_arg(
128 std::forward<std::tuple_element_t<I, Out>>(std::get<I>(args)));
130 template <size_t I, typename... Args>
131 decltype(auto) get_emplace_arg(emplace_args<Args...>& args) noexcept {
132 return detail::unwrap_emplace_arg(std::get<I>(args));
134 template <size_t I, typename... Args>
135 decltype(auto) get_emplace_arg(const emplace_args<Args...>& args) noexcept {
136 return detail::unwrap_emplace_arg(std::get<I>(args));
138 template <size_t I, typename Args>
139 decltype(auto) get_emplace_arg(Args&& args) noexcept {
140 return std::get<I>(std::move(args));
142 template <size_t I, typename Args>
143 decltype(auto) get_emplace_arg(Args& args) noexcept {
144 return std::get<I>(args);
146 template <size_t I, typename Args>
147 decltype(auto) get_emplace_arg(const Args& args) noexcept {
148 return std::get<I>(args);
153 * Emplace implementation class for folly::emplace_iterator.
155 template <typename Container>
157 Emplace(Container& c, typename Container::iterator i)
158 : container(std::addressof(c)), iter(std::move(i)) {}
159 template <typename... Args>
160 void emplace(Args&&... args) {
161 iter = container->emplace(iter, std::forward<Args>(args)...);
164 Container* container;
165 typename Container::iterator iter;
169 * Emplace implementation class for folly::hint_emplace_iterator.
171 template <typename Container>
173 EmplaceHint(Container& c, typename Container::iterator i)
174 : container(std::addressof(c)), iter(std::move(i)) {}
175 template <typename... Args>
176 void emplace(Args&&... args) {
177 iter = container->emplace_hint(iter, std::forward<Args>(args)...);
180 Container* container;
181 typename Container::iterator iter;
185 * Emplace implementation class for folly::front_emplace_iterator.
187 template <typename Container>
188 struct EmplaceFront {
189 explicit EmplaceFront(Container& c) : container(std::addressof(c)) {}
190 template <typename... Args>
191 void emplace(Args&&... args) {
192 container->emplace_front(std::forward<Args>(args)...);
194 Container* container;
198 * Emplace implementation class for folly::back_emplace_iterator.
200 template <typename Container>
202 explicit EmplaceBack(Container& c) : container(std::addressof(c)) {}
203 template <typename... Args>
204 void emplace(Args&&... args) {
205 container->emplace_back(std::forward<Args>(args)...);
207 Container* container;
211 * Generic base class and implementation of all emplace iterator classes.
213 * Uses the curiously recurring template pattern (CRTP) to cast `this*` to
214 * `Derived*`; i.e., to implement covariant return types in a generic manner.
216 template <typename Derived, typename EmplaceImpl, bool implicit_unpack>
217 class emplace_iterator_base;
220 * Partial specialization of emplace_iterator_base with implicit unpacking
223 template <typename Derived, typename EmplaceImpl>
224 class emplace_iterator_base<Derived, EmplaceImpl, false>
225 : protected EmplaceImpl /* protected implementation inheritance */ {
228 using iterator_category = std::output_iterator_tag;
229 using value_type = void;
230 using difference_type = void;
231 using pointer = void;
232 using reference = void;
233 using container_type =
234 std::remove_reference_t<decltype(*EmplaceImpl::container)>;
236 using EmplaceImpl::EmplaceImpl;
239 * Canonical output operator. Forwards single argument straight to container's
242 template <typename T>
243 Derived& operator=(T&& arg) {
244 this->emplace(std::forward<T>(arg));
245 return static_cast<Derived&>(*this);
249 * Special output operator for packed arguments. Unpacks args and performs
250 * variadic call to container's emplace function.
252 template <typename... Args>
253 Derived& operator=(emplace_args<Args...>& args) {
254 return unpackAndEmplace(args, std::index_sequence_for<Args...>{});
256 template <typename... Args>
257 Derived& operator=(const emplace_args<Args...>& args) {
258 return unpackAndEmplace(args, std::index_sequence_for<Args...>{});
260 template <typename... Args>
261 Derived& operator=(emplace_args<Args...>&& args) {
262 return unpackAndEmplace(
263 std::move(args), std::index_sequence_for<Args...>{});
267 Derived& operator*() {
268 return static_cast<Derived&>(*this);
270 Derived& operator++() {
271 return static_cast<Derived&>(*this);
273 Derived& operator++(int) {
274 return static_cast<Derived&>(*this);
277 // We need all of these explicit defaults because the custom operator=
278 // overloads disable implicit generation of these functions.
279 emplace_iterator_base(const emplace_iterator_base&) = default;
280 emplace_iterator_base(emplace_iterator_base&&) noexcept = default;
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;
286 template <typename Args, std::size_t... I>
287 Derived& unpackAndEmplace(Args& args, std::index_sequence<I...>) {
288 this->emplace(get_emplace_arg<I>(args)...);
289 return static_cast<Derived&>(*this);
291 template <typename Args, std::size_t... I>
292 Derived& unpackAndEmplace(const Args& args, std::index_sequence<I...>) {
293 this->emplace(get_emplace_arg<I>(args)...);
294 return static_cast<Derived&>(*this);
296 template <typename Args, std::size_t... I>
297 Derived& unpackAndEmplace(Args&& args, std::index_sequence<I...>) {
298 this->emplace(get_emplace_arg<I>(std::move(args))...);
299 return static_cast<Derived&>(*this);
304 * Partial specialization of emplace_iterator_base with implicit unpacking
307 * Uses inheritance rather than SFINAE. operator= requires a single argument,
308 * which makes it very tricky to use std::enable_if or similar.
310 template <typename Derived, typename EmplaceImpl>
311 class emplace_iterator_base<Derived, EmplaceImpl, true>
312 : public emplace_iterator_base<Derived, EmplaceImpl, false> {
314 using Base = emplace_iterator_base<Derived, EmplaceImpl, false>;
318 using Base::operator=;
321 * Special output operator for arguments packed into a std::pair. Unpacks
322 * the pair and performs variadic call to container's emplace function.
324 template <typename... Args>
325 Derived& operator=(std::pair<Args...>& args) {
326 return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{});
328 template <typename... Args>
329 Derived& operator=(const std::pair<Args...>& args) {
330 return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{});
332 template <typename... Args>
333 Derived& operator=(std::pair<Args...>&& args) {
334 return this->unpackAndEmplace(
335 std::move(args), std::index_sequence_for<Args...>{});
339 * Special output operator for arguments packed into a std::tuple. Unpacks
340 * the tuple and performs variadic call to container's emplace function.
342 template <typename... Args>
343 Derived& operator=(std::tuple<Args...>& args) {
344 return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{});
346 template <typename... Args>
347 Derived& operator=(const std::tuple<Args...>& args) {
348 return this->unpackAndEmplace(args, std::index_sequence_for<Args...>{});
350 template <typename... Args>
351 Derived& operator=(std::tuple<Args...>&& args) {
352 return this->unpackAndEmplace(
353 std::move(args), std::index_sequence_for<Args...>{});
356 // We need all of these explicit defaults because the custom operator=
357 // overloads disable implicit generation of these functions.
358 emplace_iterator_base(const emplace_iterator_base&) = default;
359 emplace_iterator_base(emplace_iterator_base&&) noexcept = default;
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;
366 * Concrete instantiation of emplace_iterator_base. All emplace iterator
367 * classes; folly::emplace_iterator, folly::hint_emplace_iterator,
368 * folly::front_emplace_iterator, and folly::back_emplace_iterator; are just
369 * type aliases of this class.
371 * It is not possible to alias emplace_iterator_base directly, because type
372 * aliases cannot be used for CRTP.
375 template <typename> class EmplaceImplT,
377 bool implicit_unpack>
378 class emplace_iterator_impl
379 : public emplace_iterator_base<
380 emplace_iterator_impl<EmplaceImplT, Container, implicit_unpack>,
381 EmplaceImplT<Container>,
384 using Base = emplace_iterator_base<
385 emplace_iterator_impl,
386 EmplaceImplT<Container>,
391 using Base::operator=;
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;
404 * Behaves just like std::insert_iterator except that it calls emplace()
405 * instead of insert(). Uses perfect forwarding.
407 template <typename Container, bool implicit_unpack = true>
408 using emplace_iterator =
409 detail::emplace_iterator_impl<detail::Emplace, Container, implicit_unpack>;
412 * Behaves just like std::insert_iterator except that it calls emplace_hint()
413 * instead of insert(). Uses perfect forwarding.
415 template <typename Container, bool implicit_unpack = true>
416 using hint_emplace_iterator = detail::
417 emplace_iterator_impl<detail::EmplaceHint, Container, implicit_unpack>;
420 * Behaves just like std::front_insert_iterator except that it calls
421 * emplace_front() instead of insert(). Uses perfect forwarding.
423 template <typename Container, bool implicit_unpack = true>
424 using front_emplace_iterator = detail::
425 emplace_iterator_impl<detail::EmplaceFront, Container, implicit_unpack>;
428 * Behaves just like std::back_insert_iterator except that it calls
429 * emplace_back() instead of insert(). Uses perfect forwarding.
431 template <typename Container, bool implicit_unpack = true>
432 using back_emplace_iterator = detail::
433 emplace_iterator_impl<detail::EmplaceBack, Container, implicit_unpack>;
436 * Convenience function to construct a folly::emplace_iterator, analogous to
439 * Setting implicit_unpack to false will disable implicit unpacking of
440 * single std::pair and std::tuple arguments to the iterator's operator=. That
441 * may be desirable in case of constructors that expect a std::pair or
442 * std::tuple argument.
444 template <bool implicit_unpack = true, typename Container>
445 emplace_iterator<Container, implicit_unpack> emplacer(
447 typename Container::iterator i) {
448 return emplace_iterator<Container, implicit_unpack>(c, std::move(i));
452 * Convenience function to construct a folly::hint_emplace_iterator, analogous
453 * to std::inserter().
455 * Setting implicit_unpack to false will disable implicit unpacking of
456 * single std::pair and std::tuple arguments to the iterator's operator=. That
457 * may be desirable in case of constructors that expect a std::pair or
458 * std::tuple argument.
460 template <bool implicit_unpack = true, typename Container>
461 hint_emplace_iterator<Container, implicit_unpack> hint_emplacer(
463 typename Container::iterator i) {
464 return hint_emplace_iterator<Container, implicit_unpack>(c, std::move(i));
468 * Convenience function to construct a folly::front_emplace_iterator, analogous
469 * to std::front_inserter().
471 * Setting implicit_unpack to false will disable implicit unpacking of
472 * single std::pair and std::tuple arguments to the iterator's operator=. That
473 * may be desirable in case of constructors that expect a std::pair or
474 * std::tuple argument.
476 template <bool implicit_unpack = true, typename Container>
477 front_emplace_iterator<Container, implicit_unpack> front_emplacer(
479 return front_emplace_iterator<Container, implicit_unpack>(c);
483 * Convenience function to construct a folly::back_emplace_iterator, analogous
484 * to std::back_inserter().
486 * Setting implicit_unpack to false will disable implicit unpacking of
487 * single std::pair and std::tuple arguments to the iterator's operator=. That
488 * may be desirable in case of constructors that expect a std::pair or
489 * std::tuple argument.
491 template <bool implicit_unpack = true, typename Container>
492 back_emplace_iterator<Container, implicit_unpack> back_emplacer(Container& c) {
493 return back_emplace_iterator<Container, implicit_unpack>(c);