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
19namespace boost {
20
21namespace optional_detail {
22
23template <bool use_default_constructor> struct swap_selector;
24
25template <>
26struct 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
62template <>
63struct 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
96template<class T>
97struct optional_swap_should_use_default_constructor : boost::false_type {} ;
98
99#else
100
101template<class T>
102struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
103
104#endif
105
106template <class T>
107inline 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