optional_swap.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
  2. // Copyright (C) 2015 Andrzej Krzemienski.
  3. //
  4. // Use, modification, and distribution is subject to the Boost Software
  5. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/optional for documentation.
  9. //
  10. // You are welcome to contact the author at:
  11. // akrzemi1@gmail.com
  12. #ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
  13. #define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
  14. #include <boost/core/swap.hpp>
  15. #include <boost/optional/optional_fwd.hpp>
  16. namespace boost {
  17. namespace optional_detail {
  18. template <bool use_default_constructor> struct swap_selector;
  19. template <>
  20. struct swap_selector<true>
  21. {
  22. template <class T>
  23. static void optional_swap ( optional<T>& x, optional<T>& y )
  24. {
  25. const bool hasX = !!x;
  26. const bool hasY = !!y;
  27. if ( !hasX && !hasY )
  28. return;
  29. if( !hasX )
  30. x.emplace();
  31. else if ( !hasY )
  32. y.emplace();
  33. // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
  34. boost::swap(x.get(), y.get());
  35. if( !hasX )
  36. y = boost::none ;
  37. else if( !hasY )
  38. x = boost::none ;
  39. }
  40. };
  41. #ifdef BOOST_OPTIONAL_DETAIL_MOVE
  42. # undef BOOST_OPTIONAL_DETAIL_MOVE
  43. #endif
  44. #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
  45. # define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) boost::move(EXPR_)
  46. #else
  47. # define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_
  48. #endif
  49. template <>
  50. struct swap_selector<false>
  51. {
  52. template <class T>
  53. static void optional_swap ( optional<T>& x, optional<T>& y )
  54. //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
  55. {
  56. if (x)
  57. {
  58. if (y)
  59. {
  60. boost::swap(*x, *y);
  61. }
  62. else
  63. {
  64. y = BOOST_OPTIONAL_DETAIL_MOVE(*x);
  65. x = boost::none;
  66. }
  67. }
  68. else
  69. {
  70. if (y)
  71. {
  72. x = BOOST_OPTIONAL_DETAIL_MOVE(*y);
  73. y = boost::none;
  74. }
  75. }
  76. }
  77. };
  78. } // namespace optional_detail
  79. #if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION)
  80. template<class T>
  81. struct optional_swap_should_use_default_constructor : boost::false_type {} ;
  82. #else
  83. template<class T>
  84. struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
  85. #endif
  86. template <class T>
  87. inline void swap ( optional<T>& x, optional<T>& y )
  88. //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
  89. {
  90. optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
  91. }
  92. } // namespace boost
  93. #undef BOOST_OPTIONAL_DETAIL_MOVE
  94. #endif // header guard