From e6420f2bbdaf3582a97c0a3f5aae21040ade3dad Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 18 May 2013 21:37:54 +0900 Subject: [PATCH] move support: optional class template --- sprout/optional/make_optional.hpp | 14 +- sprout/optional/optional.hpp | 160 +++++++++++-------- sprout/utility/value_holder/value_holder.hpp | 27 +++- 3 files changed, 130 insertions(+), 71 deletions(-) diff --git a/sprout/optional/make_optional.hpp b/sprout/optional/make_optional.hpp index a83af000..9303242f 100644 --- a/sprout/optional/make_optional.hpp +++ b/sprout/optional/make_optional.hpp @@ -1,22 +1,24 @@ #ifndef SPROUT_OPTIONAL_MAKE_OPTIONAL_HPP #define SPROUT_OPTIONAL_MAKE_OPTIONAL_HPP +#include #include #include +#include namespace sprout { // // make_optional // template - inline SPROUT_CONSTEXPR sprout::optional - make_optional(T const& v) { - return optional(v); + inline SPROUT_CONSTEXPR sprout::optional::type> + make_optional(T&& v) { + return sprout::optional::type>(sprout::forward(v)); } template - inline SPROUT_CONSTEXPR sprout::optional - make_optional(bool cond, T const& v) { - return optional(cond, v); + inline SPROUT_CONSTEXPR sprout::optional::type> + make_optional(bool cond, T&& v) { + return sprout::optional::type>(cond, sprout::forward(v)); } } // namespace sprout diff --git a/sprout/optional/optional.hpp b/sprout/optional/optional.hpp index ee61baa4..69bdb22e 100644 --- a/sprout/optional/optional.hpp +++ b/sprout/optional/optional.hpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,6 +32,7 @@ namespace sprout { typedef typename holder_type::pointer_type pointer_type; typedef typename holder_type::pointer_const_type pointer_const_type; typedef typename holder_type::argument_type argument_type; + typedef typename holder_type::movable_argument_type movable_argument_type; private: bool init; holder_type val; @@ -38,43 +41,63 @@ namespace sprout { init = false; } public: - // 20.5.4.1, constructors + // 20.6.4.1, constructors SPROUT_CONSTEXPR optional() SPROUT_NOEXCEPT : init(false) {} SPROUT_CONSTEXPR optional(sprout::nullopt_t) SPROUT_NOEXCEPT : init(false) {} - SPROUT_CONSTEXPR optional(argument_type v) - : init(true) - , val(v) - {} - SPROUT_CONSTEXPR optional(bool cond, argument_type v) - : init(cond) - , val(cond ? holder_type(v) : holder_type()) - {} SPROUT_CONSTEXPR optional(optional const& v) : init(v.init) , val(v.is_initialized() ? holder_type(*v) : holder_type()) {} + SPROUT_CONSTEXPR optional(optional&& v) + : init(v.init) + , val(v.is_initialized() ? holder_type(sprout::move(*v)) : holder_type()) + {} + SPROUT_CONSTEXPR optional(T const& v) + : init(true) + , val(v) + {} + SPROUT_CONSTEXPR optional(T&& v) + : init(true) + , val(sprout::move(v)) + {} + SPROUT_CONSTEXPR optional(bool cond, T const& v) + : init(cond) + , val(cond ? holder_type(v) : holder_type()) + {} + SPROUT_CONSTEXPR optional(bool cond, T&& v) + : init(cond) + , val(cond ? holder_type(sprout::move(v)) : holder_type()) + {} template explicit SPROUT_CONSTEXPR optional(optional const& v) : init(v.is_initialized()) , val(v.is_initialized() ? holder_type(*v) : holder_type()) {} - // 20.5.4.3, assignment + // 20.6.4.3, assignment optional& operator=(sprout::nullopt_t v) SPROUT_NOEXCEPT { assign(v); return *this; } - optional& operator=(argument_type v) { - assign(v); - return *this; - } optional& operator=(optional const& v) { assign(v); return *this; } + optional& operator=(optional&& v) { + assign(sprout::forward(v)); + return *this; + } + optional& operator=(T const& v) { + assign(v); + return *this; + } + optional& operator=(T&& v) { + assign(sprout::forward(v)); + return *this; + } template optional& operator=(optional const& v) { assign(v); @@ -84,14 +107,22 @@ namespace sprout { void assign(sprout::nullopt_t) SPROUT_NOEXCEPT { destroy(); } - void assign(argument_type v) { + void assign(optional const& v) { optional temp(v); temp.swap(*this); } - void assign(optional const& v) { + void assign(optional&& v) { + optional temp(sprout::forward(v)); + temp.swap(*this); + } + void assign(T const& v) { optional temp(v); temp.swap(*this); } + void assign(T&& v) { + optional temp(sprout::forward(v)); + temp.swap(*this); + } template void assign(optional const& v) { optional temp(v); @@ -104,61 +135,20 @@ namespace sprout { void reset(sprout::nullopt_t v) SPROUT_NOEXCEPT { assign(v); } - void reset(argument_type v) { + void reset(T const& v) { assign(v); } - // 20.5.4.4, swap + void reset(T&& v) { + assign(sprout::forward(v)); + } + // 20.6.4.4, swap void swap(optional& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(val, other.val))) { sprout::swap(init, other.init); sprout::swap(val, other.val); } - // 20.5.4.5, observers - SPROUT_CONSTEXPR reference_const_type operator*() const { - return (SPROUT_ASSERT(is_initialized()), true) ? val.get() - : val.get() - ; - } - reference_type operator*() { - return (SPROUT_ASSERT(is_initialized()), true) ? val.get() - : val.get() - ; - } - SPROUT_CONSTEXPR reference_const_type get() const { - return is_initialized() ? val.get() - : (throw sprout::bad_optional_access("optional<>: bad optional access"), val.get()) - ; - } - reference_type get() { - return is_initialized() ? val.get() - : (throw sprout::bad_optional_access("optional<>: bad optional access"), val.get()) - ; - } - SPROUT_CONSTEXPR reference_const_type get_value_or(reference_const_type& v) const { - return is_initialized() ? val.get() - : v - ; - } - reference_type get_value_or(reference_type& v) { - return is_initialized() ? val.get() - : v - ; - } - - SPROUT_CONSTEXPR reference_const_type value() const { - return get(); - } - reference_type value() { - return get(); - } - SPROUT_CONSTEXPR reference_const_type value_or(reference_const_type& v) const { - return get_value_or(v); - } - reference_type value_or(reference_type& v) { - return get_value_or(v); - } - + // 20.6.4.5, observers SPROUT_CONSTEXPR pointer_const_type operator->() const { return SPROUT_ASSERT(is_initialized()), val.get_pointer() @@ -186,6 +176,50 @@ namespace sprout { return get_pointer(); } + SPROUT_CONSTEXPR reference_const_type operator*() const { + return (SPROUT_ASSERT(is_initialized()), true) ? val.get() + : val.get() + ; + } + reference_type operator*() { + return (SPROUT_ASSERT(is_initialized()), true) ? val.get() + : val.get() + ; + } + SPROUT_CONSTEXPR reference_const_type value() const { + return get(); + } + reference_type value() { + return get(); + } + SPROUT_CONSTEXPR reference_const_type get() const { + return is_initialized() ? val.get() + : (throw sprout::bad_optional_access("optional<>: bad optional access"), val.get()) + ; + } + reference_type get() { + return is_initialized() ? val.get() + : (throw sprout::bad_optional_access("optional<>: bad optional access"), val.get()) + ; + } + + SPROUT_CONSTEXPR reference_const_type value_or(reference_const_type& v) const { + return get_value_or(v); + } + reference_type value_or(reference_type& v) { + return get_value_or(v); + } + SPROUT_CONSTEXPR reference_const_type get_value_or(reference_const_type& v) const { + return is_initialized() ? val.get() + : v + ; + } + reference_type get_value_or(reference_type& v) { + return is_initialized() ? val.get() + : v + ; + } + SPROUT_CONSTEXPR operator bool() const SPROUT_NOEXCEPT { return is_initialized(); } diff --git a/sprout/utility/value_holder/value_holder.hpp b/sprout/utility/value_holder/value_holder.hpp index d4e45fda..95334549 100644 --- a/sprout/utility/value_holder/value_holder.hpp +++ b/sprout/utility/value_holder/value_holder.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace sprout { namespace detail { @@ -17,11 +18,15 @@ namespace sprout { typedef T const* const_pointer; typedef T const* mutable_or_const_pointer; typedef T const& param_type; + typedef T&& movable_param_type; typedef T holder_type; public: static SPROUT_CONSTEXPR holder_type const& hold(param_type p) SPROUT_NOEXCEPT { return p; } + static SPROUT_CONSTEXPR holder_type&& hold(movable_param_type p) SPROUT_NOEXCEPT { + return sprout::move(p); + } static SPROUT_CONSTEXPR reference ref(holder_type& r) { return r; } @@ -46,10 +51,14 @@ namespace sprout { typedef T const* const_pointer; typedef T const* mutable_or_const_pointer; typedef T const& param_type; + typedef T const&& movable_param_type; typedef T holder_type; public: static SPROUT_CONSTEXPR holder_type const& hold(param_type p) SPROUT_NOEXCEPT { - return &p; + return p; + } + static SPROUT_CONSTEXPR holder_type const&& hold(movable_param_type p) SPROUT_NOEXCEPT { + return sprout::move(p); } static SPROUT_CONSTEXPR reference ref(holder_type& r) { return *r; @@ -75,6 +84,7 @@ namespace sprout { typedef T const* const_pointer; typedef T* mutable_or_const_pointer; typedef T& param_type; + typedef T&& movable_param_type; typedef T* holder_type; public: static SPROUT_CONSTEXPR holder_type hold(param_type p) SPROUT_NOEXCEPT { @@ -98,6 +108,7 @@ namespace sprout { typedef T const* const_pointer; typedef T const* mutable_or_const_pointer; typedef T const& param_type; + typedef T const&& movable_param_type; typedef T const* holder_type; public: static SPROUT_CONSTEXPR holder_type hold(param_type p) SPROUT_NOEXCEPT { @@ -130,11 +141,13 @@ namespace sprout { typedef typename helper_type::const_pointer const_pointer; typedef typename helper_type::mutable_or_const_pointer mutable_or_const_pointer; typedef typename helper_type::param_type param_type; + typedef typename helper_type::movable_param_type movable_param_type; typedef reference reference_type; typedef mutable_or_const_reference reference_const_type; typedef pointer pointer_type; typedef mutable_or_const_pointer pointer_const_type; typedef param_type argument_type; + typedef movable_param_type movable_argument_type; private: holder_type holder_; public: @@ -142,13 +155,23 @@ namespace sprout { : holder_() {} SPROUT_CONSTEXPR value_holder(value_holder const&) = default; + SPROUT_CONSTEXPR value_holder(value_holder&&) = default; explicit SPROUT_CONSTEXPR value_holder(param_type p) : holder_(helper_type::hold(p)) {} + explicit SPROUT_CONSTEXPR value_holder(movable_argument_type p) + : holder_(helper_type::hold(sprout::move(p))) + {} value_holder& operator=(value_holder const&) = default; + value_holder& operator=(value_holder&&) = default; value_holder& operator=(param_type p) { - value_holder temp(p); + value_holder temp(helper_type::hold(p)); + temp.swap(p); + return *this; + } + value_holder& operator=(movable_argument_type p) { + value_holder temp(helper_type::hold(sprout::move(p))); temp.swap(p); return *this; }