MoveWrapper.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright 2013-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. #pragma once
  17. #include <memory>
  18. namespace folly {
  19. /** C++11 closures don't support move-in capture. Nor does std::bind.
  20. facepalm.
  21. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3610.html
  22. "[...] a work-around that should make people's stomach crawl:
  23. write a wrapper that performs move-on-copy, much like the deprecated
  24. auto_ptr"
  25. Unlike auto_ptr, this doesn't require a heap allocation.
  26. */
  27. template <class T>
  28. class MoveWrapper {
  29. public:
  30. /** If value can be default-constructed, why not?
  31. Then we don't have to move it in */
  32. MoveWrapper() = default;
  33. /// Move a value in.
  34. explicit MoveWrapper(T&& t) : value(std::move(t)) {}
  35. /// copy is move
  36. MoveWrapper(const MoveWrapper& other) : value(std::move(other.value)) {}
  37. /// move is also move
  38. MoveWrapper(MoveWrapper&& other) : value(std::move(other.value)) {}
  39. const T& operator*() const {
  40. return value;
  41. }
  42. T& operator*() {
  43. return value;
  44. }
  45. const T* operator->() const {
  46. return &value;
  47. }
  48. T* operator->() {
  49. return &value;
  50. }
  51. /// move the value out (sugar for std::move(*moveWrapper))
  52. T&& move() {
  53. return std::move(value);
  54. }
  55. // If you want these you're probably doing it wrong, though they'd be
  56. // easy enough to implement
  57. MoveWrapper& operator=(MoveWrapper const&) = delete;
  58. MoveWrapper& operator=(MoveWrapper&&) = delete;
  59. private:
  60. mutable T value;
  61. };
  62. /// Make a MoveWrapper from the argument. Because the name "makeMoveWrapper"
  63. /// is already quite transparent in its intent, this will work for lvalues as
  64. /// if you had wrapped them in std::move.
  65. template <class T, class T0 = typename std::remove_reference<T>::type>
  66. MoveWrapper<T0> makeMoveWrapper(T&& t) {
  67. return MoveWrapper<T0>(std::forward<T0>(t));
  68. }
  69. } // namespace folly