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 
13 #ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
14 #define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
15 
16 #include <boost/core/swap.hpp>
17 #include <boost/optional/optional_fwd.hpp>
18 
19 namespace boost {
20 
21 namespace optional_detail {
22 
23 template <bool use_default_constructor> struct swap_selector;
24 
25 template <>
26 struct swap_selector<true>
27 {
28     template <class T>
optional_swapboost::optional_detail::swap_selector29     static void optional_swap ( optional<T>& x, optional<T>& y )
30     {
31         const bool hasX = !!x;
32         const bool hasY = !!y;
33 
34         if ( !hasX && !hasY )
35             return;
36 
37         if( !hasX )
38             x.emplace();
39         else if ( !hasY )
40             y.emplace();
41 
42         // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
43         boost::swap(x.get(), y.get());
44 
45         if( !hasX )
46             y = boost::none ;
47         else if( !hasY )
48             x = boost::none ;
49     }
50 };
51 
52 #ifdef BOOST_OPTIONAL_DETAIL_MOVE
53 # undef BOOST_OPTIONAL_DETAIL_MOVE
54 #endif
55 
56 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
57 # define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) boost::move(EXPR_)
58 #else
59 # define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_
60 #endif
61 
62 template <>
63 struct swap_selector<false>
64 {
65     template <class T>
optional_swapboost::optional_detail::swap_selector66     static void optional_swap ( optional<T>& x, optional<T>& y )
67     //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
68     {
69         if (x)
70         {
71             if (y)
72             {
73                 boost::swap(*x, *y);
74             }
75             else
76             {
77                 y = BOOST_OPTIONAL_DETAIL_MOVE(*x);
78                 x = boost::none;
79             }
80         }
81         else
82         {
83             if (y)
84             {
85                 x = BOOST_OPTIONAL_DETAIL_MOVE(*y);
86                 y = boost::none;
87             }
88         }
89     }
90 };
91 
92 } // namespace optional_detail
93 
94 #if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION)
95 
96 template<class T>
97 struct optional_swap_should_use_default_constructor : boost::false_type {} ;
98 
99 #else
100 
101 template<class T>
102 struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
103 
104 #endif
105 
106 template <class T>
swap(optional<T> & x,optional<T> & y)107 inline void swap ( optional<T>& x, optional<T>& y )
108 //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
109 {
110     optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
111 }
112 
113 } // namespace boost
114 
115 #undef BOOST_OPTIONAL_DETAIL_MOVE
116 
117 #endif // header guard
118