From dbab91a53c810b5c14777396bafed2da9c475aaf Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Sat, 15 Jun 2013 22:14:24 +0900 Subject: [PATCH] add forward_clist: C++14 constexpr based forward list --- sprout/config/suffix.hpp | 5 + sprout/forward_clist.hpp | 457 +++++++++++++++++++ sprout/utility/value_holder/value_holder.hpp | 8 +- 3 files changed, 466 insertions(+), 4 deletions(-) create mode 100644 sprout/forward_clist.hpp diff --git a/sprout/config/suffix.hpp b/sprout/config/suffix.hpp index 42167652..46b2684c 100644 --- a/sprout/config/suffix.hpp +++ b/sprout/config/suffix.hpp @@ -24,6 +24,11 @@ # define SPROUT_STATIC_CONSTEXPR_DATA_MEMBER_OUTER(EXPR) = EXPR #endif // #ifndef SPROUT_CONFIG_DISABLE_CONSTEXPR +// +// SPROUT_CXX14_CONSTEXPR +// +#define SPROUT_CXX14_CONSTEXPR + // // SPROUT_DEFAULTED_DEFAULT_CONSTRUCTOR_DECL // SPROUT_DEFAULTED_DESTRUCTOR_DECL diff --git a/sprout/forward_clist.hpp b/sprout/forward_clist.hpp new file mode 100644 index 00000000..b219a5ca --- /dev/null +++ b/sprout/forward_clist.hpp @@ -0,0 +1,457 @@ +#ifndef SPROUT_FORWARD_CLIST_HPP +#define SPROUT_FORWARD_CLIST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + // + // forward_clist + // + template + class forward_clist; + + namespace detail { + template + class forward_item_iterator + : public std::iterator< + std::forward_iterator_tag, + typename List::value_type, + typename List::difference_type, + typename std::conditional< + std::is_const::type>::value, + typename List::const_pointer, + typename List::pointer + >::type, + typename std::conditional< + std::is_const::type>::value, + typename List::const_reference, + typename List::reference + >::type + > + { + template + friend class sprout::forward_clist; + public: + typedef List list_type; + typedef typename std::conditional< + std::is_reference::value, + typename std::remove_reference::type const&, + typename std::remove_reference::type const + >::type const_list_type; + private: + typedef std::iterator< + std::forward_iterator_tag, + typename List::value_type, + typename List::difference_type, + typename std::conditional< + std::is_const::type>::value, + typename List::const_pointer, + typename List::pointer + >::type, + typename std::conditional< + std::is_const::type>::value, + typename List::const_reference, + typename List::reference + >::type + > base_type; + typedef typename std::remove_reference::type::item_holder_type item_holder_type; + public: + typedef typename base_type::iterator_category iterator_category; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::reference reference; + private: + item_holder_type item; + private: + explicit SPROUT_CONSTEXPR forward_item_iterator(item_holder_type const& p) + : item(p) + {} + public: + SPROUT_CONSTEXPR forward_item_iterator() + : item() + {} + forward_item_iterator(forward_item_iterator const&) = default; + operator forward_item_iterator() const { + return forward_item_iterator(item); + } + SPROUT_CONSTEXPR forward_item_iterator next() const { + return forward_item_iterator(item->next); + } + void swap(forward_item_iterator& other) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(item, other.item))) + { + sprout::swap(item, other.item); + } + SPROUT_CONSTEXPR reference operator*() const { + return item->get(); + } + SPROUT_CONSTEXPR pointer operator->() const { + return item->get_pointer(); + } + forward_item_iterator& operator++() { + forward_item_iterator temp(next()); + temp.swap(*this); + return *this; + } + forward_item_iterator operator++(int) { + forward_item_iterator result(*this); + ++*this; + return result; + } + }; + + template + inline SPROUT_CONSTEXPR typename std::enable_if< + std::is_same::type, typename std::decay::type>::value, + bool + >::type + operator==(sprout::detail::forward_item_iterator const& lhs, sprout::detail::forward_item_iterator const& rhs) { + return &*lhs == &*rhs; + } + template + inline SPROUT_CONSTEXPR typename std::enable_if< + std::is_same::type, typename std::decay::type>::value, + bool + >::type + operator!=(sprout::detail::forward_item_iterator const& lhs, sprout::detail::forward_item_iterator const& rhs) { + return !(lhs == rhs); + } + + template + inline void + swap(sprout::detail::forward_item_iterator& lhs, sprout::detail::forward_item_iterator& rhs) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } + + template + inline SPROUT_CONSTEXPR sprout::detail::forward_item_iterator + iterator_next(sprout::detail::forward_item_iterator const& it) { + return it.next(); + } + } // namespace detail + + // + // forward_clist + // + template + class forward_clist { + template + friend class sprout::detail::forward_item_iterator; + public: + // types: + typedef T value_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type const* const_pointer; + typedef sprout::detail::forward_item_iterator iterator; + typedef sprout::detail::forward_item_iterator const_iterator; + public: + class item; + private: + typedef sprout::value_holder item_holder_type; + public: + // + // item + // + class item { + friend class forward_clist; + template + friend class sprout::detail::forward_item_iterator; + private: + typedef sprout::value_holder holder_type; + typedef sprout::value_holder item_holder_type; + public: + typedef typename holder_type::value_type value_type; + typedef typename holder_type::lvalue_reference lvalue_reference; + typedef typename holder_type::rvalue_reference rvalue_reference; + typedef typename holder_type::reference reference; + typedef typename holder_type::const_lvalue_reference const_lvalue_reference; + typedef typename holder_type::const_rvalue_reference const_rvalue_reference; + typedef typename holder_type::const_reference const_reference; + typedef typename holder_type::pointer pointer; + typedef typename holder_type::const_pointer const_pointer; + typedef typename holder_type::lvalue_reference_type lvalue_reference_type; + typedef typename holder_type::rvalue_reference_type rvalue_reference_type; + typedef typename holder_type::reference_type reference_type; + typedef typename holder_type::reference_const_type reference_const_type; + typedef typename holder_type::pointer_type pointer_type; + typedef typename holder_type::pointer_const_type pointer_const_type; + public: + static SPROUT_CONSTEXPR reference_type get(item& t) SPROUT_NOEXCEPT { + return sprout::get(t.val); + } + static SPROUT_CONSTEXPR rvalue_reference_type get(item&& t) SPROUT_NOEXCEPT { + return static_cast(get(t)); + } + static SPROUT_CONSTEXPR reference_const_type get(item const& t) SPROUT_NOEXCEPT { + return sprout::get(t.val); + } + static SPROUT_CONSTEXPR pointer_type get_pointer(item& t) SPROUT_NOEXCEPT { + return sprout::get_pointer(t.val); + } + static SPROUT_CONSTEXPR pointer_type get_pointer(item&& t) SPROUT_NOEXCEPT { + return get_pointer(t); + } + static SPROUT_CONSTEXPR pointer_const_type get_pointer(item const& t) SPROUT_NOEXCEPT { + return sprout::get_pointer(t.val); + } + private: + holder_type val; + item_holder_type next; + private: + SPROUT_CONSTEXPR item(item const&) = default; + SPROUT_CONSTEXPR item(typename holder_type::argument_type p, item_holder_type const& n) + : val(p) + , next(n) + {} + SPROUT_CONSTEXPR item(typename holder_type::movable_argument_type p, item_holder_type const& n) + : val(sprout::move(p)) + , next(n) + {} + + item& operator=(item const&) = default; + item& operator=(item&&) = default; + + void swap(item& other) + SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(val, other.val)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(next, other.next))) + { + sprout::swap(val, other.val); + sprout::swap(next, other.next); + } + + void clear() { + if (next.is_initialized()) { + (*next).clear(); + { + item_holder_type temp; + temp.swap(next); + } + } + } + void remove() { + item_holder_type temp; + temp.swap(next); + } + public: + SPROUT_CONSTEXPR item() SPROUT_NOEXCEPT + : val(), next() + {} + SPROUT_CONSTEXPR item(item&&) = default; + SPROUT_CONSTEXPR item(typename holder_type::argument_type p) + : val(p) + , next() + {} + SPROUT_CONSTEXPR item(typename holder_type::movable_argument_type p) + : val(sprout::move(p)), next() + {} + + item& operator=(typename holder_type::argument_type p) { + item temp(p, next); + temp.swap(p); + return *this; + } + item& operator=(typename holder_type::movable_argument_type p) { + item temp(sprout::move(p), next); + temp.swap(p); + return *this; + } + + pointer_type operator->() { + return get_pointer(); + } + SPROUT_CONSTEXPR pointer_const_type operator->() const { + return get_pointer(); + } + pointer_type get_pointer() { + return val.get_pointer(); + } + SPROUT_CONSTEXPR pointer_const_type get_pointer() const { + return val.get_pointer(); + } + reference_type operator*() { + return get(); + } + SPROUT_CONSTEXPR reference_const_type operator*() const { + return get(); + } + reference_type get() { + return val.get(); + } + SPROUT_CONSTEXPR reference_const_type get() const { + return val.get(); + } + }; + private: + item fst; + public: + // construct/copy/destroy: + SPROUT_CONSTEXPR forward_clist() + : fst() + {} + template + SPROUT_CXX14_CONSTEXPR forward_clist(InputIterator first, InputIterator last) + : fst() + { + item_holder_type* p = &fst.next; + for (; first != last; ++first) { + *p = *first; + p = &(**p).next; + } + } + SPROUT_CXX14_CONSTEXPR forward_clist(forward_clist&& x) + : fst(sprout::move(x.fst)) + {} + SPROUT_CXX14_CONSTEXPR forward_clist& operator=(forward_clist&& x) { + fst = sprout::move(x.fst); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR void assign(InputIterator first, InputIterator last) { + forward_clist temp(first, last); + temp.swap(*this); + temp.clear(); + } + // iterators: + SPROUT_CXX14_CONSTEXPR iterator before_begin() SPROUT_NOEXCEPT { + return iterator(item_holder_type(fst)); + } + SPROUT_CONSTEXPR const_iterator before_begin() const SPROUT_NOEXCEPT { + return const_iterator(item_holder_type(fst)); + } + SPROUT_CXX14_CONSTEXPR iterator begin() SPROUT_NOEXCEPT { + return iterator(fst.next); + } + SPROUT_CONSTEXPR const_iterator begin() const SPROUT_NOEXCEPT { + return const_iterator(fst.next); + } + SPROUT_CXX14_CONSTEXPR iterator end() SPROUT_NOEXCEPT { + return iterator(); + } + SPROUT_CONSTEXPR const_iterator end() const SPROUT_NOEXCEPT { + return const_iterator(); + } + SPROUT_CONSTEXPR const_iterator cbegin() const SPROUT_NOEXCEPT { + return const_iterator(fst.next); + } + SPROUT_CONSTEXPR const_iterator cbefore_begin() const SPROUT_NOEXCEPT{ + return const_iterator(fst.next); + } + SPROUT_CONSTEXPR const_iterator cend() const SPROUT_NOEXCEPT { + return const_iterator(); + } + // capacity: + SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { + return !!fst.next; + } + SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { + return std::numeric_limits::max(); + } + // element access: + SPROUT_CXX14_CONSTEXPR reference front() { + return fst.next->get(); + } + SPROUT_CONSTEXPR const_reference front() const { + return fst.next->get(); + } + // modifiers: + SPROUT_CXX14_CONSTEXPR void push_front(item& x) { + item_holder_type nxt(x); + (*nxt).next = sprout::move(fst.next); + fst.next = sprout::move(nxt); + } + template + SPROUT_CXX14_CONSTEXPR void push_front(InputIterator first, InputIterator last) { + item_holder_type nxt(fst.next); + item_holder_type* p = &fst.next; + for (; first != last; ++first) { + *p = *first; + p = &(**p).next; + } + *p = nxt; + } + SPROUT_CXX14_CONSTEXPR void pop_front() { + item_holder_type nxt(sprout::move(fst.next)); + fst.next = fst.next->next; + nxt->remove(); + } + SPROUT_CXX14_CONSTEXPR void pop(item& x) { + for (iterator first = before_begin(), last = end(); first != last; ++first) { + iterator nxt = first.next(); + if (nxt.item.get_pointer() == &x) { + first.item->next = sprout::move(nxt.item->next); + nxt.item->remove(); + break; + } + } + } + template + SPROUT_CXX14_CONSTEXPR void pop(InputIterator first, InputIterator last) { + for (; first != last; ++first) { + pop(*first); + } + } + }; + + // + // get + // + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::reference_type + get(typename sprout::forward_clist::item& x) { + return sprout::forward_clist::item::get(x); + } + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::rvalue_reference + get(typename sprout::forward_clist::item&& x) { + return sprout::forward_clist::item::get(sprout::move(x)); + } + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::reference_const_type + get(typename sprout::forward_clist::item const& x) { + return sprout::forward_clist::item::get(x); + } + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::pointer_type + get(typename sprout::forward_clist::item* x) { + return sprout::forward_clist::item::get_pointer(*x); + } + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::pointer_const_type + get(typename sprout::forward_clist::item const* x) { + return sprout::forward_clist::item::get_pointer(*x); + } + + // + // get_pointer + // + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::pointer_type + get_pointer(typename sprout::forward_clist::item& x) { + return sprout::forward_clist::item::get_pointer(x); + } + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::pointer_type + get_pointer(typename sprout::forward_clist::item&& x) { + return sprout::forward_clist::item::get_pointer(sprout::move(x)); + } + template + inline SPROUT_CONSTEXPR typename sprout::forward_clist::item::pointer_const_type + get_pointer(typename sprout::forward_clist::item const& x) { + return sprout::forward_clist::item::get_pointer(x); + } +} // namespace sprout + +#endif // #ifndef SPROUT_FORWARD_CLIST_HPP diff --git a/sprout/utility/value_holder/value_holder.hpp b/sprout/utility/value_holder/value_holder.hpp index 7f011009..ce441d3f 100644 --- a/sprout/utility/value_holder/value_holder.hpp +++ b/sprout/utility/value_holder/value_holder.hpp @@ -225,13 +225,13 @@ namespace sprout { value_holder& operator=(value_holder const&) = default; value_holder& operator=(value_holder&&) = default; value_holder& operator=(argument_type p) { - value_holder temp(helper_type::hold(p)); - temp.swap(p); + value_holder temp(p); + temp.swap(*this); return *this; } value_holder& operator=(movable_argument_type p) { - value_holder temp(helper_type::hold(sprout::move(p))); - temp.swap(p); + value_holder temp(sprout::move(p)); + temp.swap(*this); return *this; }