diff --git a/sprout/optional.hpp b/sprout/optional.hpp index f832d0a8..89ed657c 100644 --- a/sprout/optional.hpp +++ b/sprout/optional.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/sprout/optional/in_place.hpp b/sprout/optional/in_place.hpp new file mode 100644 index 00000000..c7b3f5f8 --- /dev/null +++ b/sprout/optional/in_place.hpp @@ -0,0 +1,17 @@ +#ifndef SPROUT_OPTIONAL_IN_PLACE_HPP +#define SPROUT_OPTIONAL_IN_PLACE_HPP + +#include + +namespace sprout { + // + // in_place_t + // in_place + // + struct in_place_t {}; + namespace { + SPROUT_STATIC_CONSTEXPR in_place_t in_place{}; + } // anonymous-namespace +} // namespace sprout + +#endif // #ifndef SPROUT_OPTIONAL_IN_PLACE_HPP diff --git a/sprout/optional/optional.hpp b/sprout/optional/optional.hpp index 69bdb22e..d8800af0 100644 --- a/sprout/optional/optional.hpp +++ b/sprout/optional/optional.hpp @@ -1,13 +1,18 @@ #ifndef SPROUT_OPTIONAL_OPTIONAL_HPP #define SPROUT_OPTIONAL_OPTIONAL_HPP +#include +#include #include #include #include #include #include +#include +#include #include #include +#include #include #include @@ -52,9 +57,16 @@ namespace sprout { : init(v.init) , val(v.is_initialized() ? holder_type(*v) : holder_type()) {} + // constexpr support +// SPROUT_CONSTEXPR optional(optional&& v) +// SPROUT_NOEXCEPT_EXPR(std::is_nothrow_move_constructible::value) +// : init(v.init) +// , val(v.is_initialized() ? holder_type(sprout::move(*v)) : holder_type()) +// {} SPROUT_CONSTEXPR optional(optional&& v) + SPROUT_NOEXCEPT_EXPR(std::is_nothrow_copy_constructible::value) : init(v.init) - , val(v.is_initialized() ? holder_type(sprout::move(*v)) : holder_type()) + , val(v.is_initialized() ? holder_type(*sprout::as_const(v)) : holder_type()) {} SPROUT_CONSTEXPR optional(T const& v) : init(true) @@ -64,6 +76,22 @@ namespace sprout { : init(true) , val(sprout::move(v)) {} + template< + typename... Args, + typename = typename std::enable_if::value>::type + > + explicit SPROUT_CONSTEXPR optional(sprout::in_place_t, Args&&... args) + : init(true) + , val(sprout::in_place, sprout::forward(args)...) + {} + template< + typename U, typename... Args, + typename = typename std::enable_if&, Args&&...>::value>::type + > + explicit SPROUT_CONSTEXPR optional(sprout::in_place_t, std::initializer_list il, Args&&... args) + : init(true) + , val(sprout::in_place, il, sprout::forward(args)...) + {} SPROUT_CONSTEXPR optional(bool cond, T const& v) : init(cond) , val(cond ? holder_type(v) : holder_type()) @@ -77,6 +105,17 @@ namespace sprout { : init(v.is_initialized()) , val(v.is_initialized() ? holder_type(*v) : holder_type()) {} + // constexpr support +// template +// explicit SPROUT_CONSTEXPR optional(optional&& v) +// : init(v.is_initialized()) +// , val(v.is_initialized() ? holder_type(sprout::move(*v)) : holder_type()) +// {} + template + explicit SPROUT_CONSTEXPR optional(optional&& v) + : init(v.is_initialized()) + , val(v.is_initialized() ? holder_type(*sprout::as_const(v)) : holder_type()) + {} // 20.6.4.3, assignment optional& operator=(sprout::nullopt_t v) SPROUT_NOEXCEPT { assign(v); @@ -86,16 +125,19 @@ namespace sprout { assign(v); return *this; } - optional& operator=(optional&& v) { + optional& operator=(optional&& v) + SPROUT_NOEXCEPT_EXPR(std::is_move_constructible::value && std::is_move_assignable::value) + { assign(sprout::forward(v)); return *this; } - optional& operator=(T const& v) { - assign(v); - return *this; - } - optional& operator=(T&& v) { - assign(sprout::forward(v)); + template< + typename U, +// typename = typename std::enable_if::value && std::is_assignable::value>::type + typename = typename std::enable_if::value>::type + > + optional& operator=(U&& v) { + assign(sprout::forward(v)); return *this; } template @@ -103,6 +145,11 @@ namespace sprout { assign(v); return *this; } + template + optional& operator=(optional&& v) { + assign(sprout::forward >(v)); + return *this; + } void assign(sprout::nullopt_t) SPROUT_NOEXCEPT { destroy(); @@ -111,16 +158,19 @@ namespace sprout { optional temp(v); temp.swap(*this); } - void assign(optional&& v) { + void assign(optional&& v) + SPROUT_NOEXCEPT_EXPR(std::is_move_constructible::value && std::is_move_assignable::value) + { 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)); + template< + typename U, +// typename = typename std::enable_if::value && std::is_assignable::value>::type + typename = typename std::enable_if::value>::type + > + void assign(U&& v) { + optional temp(sprout::forward(v)); temp.swap(*this); } template @@ -128,6 +178,11 @@ namespace sprout { optional temp(v); temp.swap(*this); } + template + void assign(optional&& v) { + optional temp(sprout::forward >(v)); + temp.swap(*this); + } void reset() SPROUT_NOEXCEPT { destroy(); @@ -135,11 +190,13 @@ namespace sprout { void reset(sprout::nullopt_t v) SPROUT_NOEXCEPT { assign(v); } - void reset(T const& v) { - assign(v); - } - void reset(T&& v) { - assign(sprout::forward(v)); + template< + typename U, +// typename = typename std::enable_if::value && std::is_assignable::value>::type + typename = typename std::enable_if::value>::type + > + void reset(U&& v) { + assign(sprout::forward(v)); } // 20.6.4.4, swap void swap(optional& other) diff --git a/sprout/utility/value_holder/value_holder.hpp b/sprout/utility/value_holder/value_holder.hpp index 95334549..e5c6c23a 100644 --- a/sprout/utility/value_holder/value_holder.hpp +++ b/sprout/utility/value_holder/value_holder.hpp @@ -1,9 +1,13 @@ #ifndef SPROUT_UTILITY_VALUE_HOLDER_VALUE_HOLDER_HPP #define SPROUT_UTILITY_VALUE_HOLDER_VALUE_HOLDER_HPP +#include +#include #include #include +#include #include +#include namespace sprout { namespace detail { @@ -162,6 +166,20 @@ namespace sprout { explicit SPROUT_CONSTEXPR value_holder(movable_argument_type p) : holder_(helper_type::hold(sprout::move(p))) {} + template< + typename... Args, + typename = typename std::enable_if::value>::type + > + explicit SPROUT_CONSTEXPR value_holder(sprout::in_place_t, Args&&... args) + : holder_(sprout::forward(args)...) + {} + template< + typename U, typename... Args, + typename = typename std::enable_if&, Args&&...>::value>::type + > + explicit SPROUT_CONSTEXPR value_holder(sprout::in_place_t, std::initializer_list il, Args&&... args) + : holder_(il, sprout::forward(args)...) + {} value_holder& operator=(value_holder const&) = default; value_holder& operator=(value_holder&&) = default; diff --git a/sprout/weed/parser/char/char.hpp b/sprout/weed/parser/char/char.hpp index b825ea33..e1e9bf42 100644 --- a/sprout/weed/parser/char/char.hpp +++ b/sprout/weed/parser/char/char.hpp @@ -111,6 +111,47 @@ namespace sprout { } }; + // + // char_range_p + // + template + struct char_range_p + : public sprout::weed::parser_base + { + public: + template + struct attribute + : public sprout::identity::value_type> + {}; + template + struct result + : public sprout::identity::type> > + {}; + private: + T f_; + T l_; + public: + char_range_p() = default; + SPROUT_CONSTEXPR char_range_p(T const& f, T const& l) + : f_(f), l_(l) + {} + template + SPROUT_CONSTEXPR typename result::type operator()( + Iterator first, + Iterator last, + Context const& + ) const + { + typedef typename result::type result_type; + typedef typename attribute::type attribute_type; + typedef typename std::iterator_traits::value_type elem_type; + return first != last && *first >= elem_type(f_) && *first <= elem_type(l_) + ? result_type(true, sprout::next(first), *first) + : result_type(false, first, attribute_type()) + ; + } + }; + // // any_char_p // @@ -142,9 +183,21 @@ namespace sprout { ; } template - SPROUT_CONSTEXPR sprout::weed::char_p operator()(T const& t) const { + SPROUT_CONSTEXPR typename std::enable_if< + sprout::weed::traits::is_char_type::value, + sprout::weed::char_p + >::type + operator()(T const& t) const { return sprout::weed::char_p(t); } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::weed::traits::is_char_type::value, + sprout::weed::char_range_p + >::type + operator()(T const& f, T const& l) const { + return sprout::weed::char_range_p(f, l); + } }; // // char_