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> |
29 | 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> |
66 | 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> |
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 | |