We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I'll just leave this here. Caveat: largely untested and probably buggy as hell.
// Copyright Eric Niebler 2016 // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) namespace any_iterator_detail { enum class op { copy, move, nuke, bump, comp }; struct counted { std::atomic<long> cnt{ 1 }; }; ranges::InputIterator{I} struct shared_iterator : counted { shared_iterator(I i) : it(std::move(i)) {} I it; }; union blob { counted* big; std::aligned_storage<2 * sizeof(void*)>::type tiny; }; template <typename It> using is_small = std::integral_constant<bool, (sizeof(It) <= sizeof(blob::tiny))>; using small_tag = std::true_type; using big_tag = std::false_type; inline bool uninit_noop(op, blob*, blob*) { return false; } template<typename Reference> [[noreturn]] inline Reference uninit_deref(blob const &) { std::terminate(); } template <typename Reference, ranges::InputIterator I> static Reference deref_small(blob const & p) { return **static_cast<I const *>(static_cast<void const *>(&p.tiny)); } template <typename Reference, ranges::InputIterator I> static Reference deref_big(blob const& p) { return *static_cast<shared_iterator<I> const *>(p.big)->it; } ranges::InputIterator{I} bool exec_small(op o, blob* src, blob* dst) { switch (o) { case op::copy: ::new (static_cast<void*>(&dst->tiny)) I(*static_cast<I const *>(static_cast<void*>(&src->tiny))); break; case op::move: ::new (static_cast<void*>(&dst->tiny)) I(std::move(*static_cast<I*>(static_cast<void*>(&src->tiny)))); // fallthrough case op::nuke: static_cast<I*>(static_cast<void*>(&src->tiny))->~I(); break; case op::bump: ++*static_cast<I*>(static_cast<void*>(&src->tiny)); break; case op::comp: return *static_cast<I const *>(static_cast<void*>(&src->tiny)) == *static_cast<I const *>(static_cast<void*>(&dst->tiny)); } return false; } ranges::InputIterator{I} bool exec_big(op o, blob* src, blob* dst) { switch (o) { case op::copy: ++(dst->big = src->big)->cnt; break; case op::move: dst->big = std::exchange(src->big, nullptr); break; case op::nuke: if (0 == --src->big->cnt) delete static_cast<shared_iterator<I>*>(src->big); break; case op::bump: ++static_cast<shared_iterator<I>*>(src->big)->it; break; case op::comp: return static_cast<shared_iterator<I> const *>(src->big)->it == static_cast<shared_iterator<I> const *>(dst->big)->it; } return true; } template<class Reference, class ValueType> struct any_input_cursor { private: blob data_ = { nullptr }; Reference (*deref_)(blob const &) = &uninit_deref<Reference>; bool (*exec_)(op, blob*, blob*) = &uninit_noop; ranges::InputIterator{I} any_input_cursor(I i, small_tag) { ::new (static_cast<void*>(&data_.tiny)) I(std::move(i)); deref_ = &deref_small<Reference, I>; exec_ = &exec_small<I>; } ranges::InputIterator{I} any_input_cursor(I i, big_tag) { data_.big = new shared_iterator<I>(std::move(i)); deref_ = &deref_big<Reference, I>; exec_ = &exec_big<I>; } public: using value_type = ValueType; using single_pass = std::true_type; any_input_cursor() = default; ranges::InputIterator{I} any_input_cursor(I i) requires ranges::ConvertibleTo<ranges::reference_t<I>, Reference>() : any_input_cursor(std::move(i), is_small<I>{}) {} any_input_cursor(any_input_cursor &&that) { that.exec_(op::move, &that.data_, &data_); ranges::swap(deref_, that.deref_); ranges::swap(exec_, that.exec_); } any_input_cursor(any_input_cursor const &that) { that.exec_(op::copy, const_cast<blob*>(&that.data_), &data_); deref_ = that.deref_; exec_ = that.exec_; } any_input_cursor& operator=(any_input_cursor &&that) { if (&that != this) { this->~any_input_cursor(); ::new (static_cast<void*>(this)) any_input_cursor(std::move(that)); } return *this; } any_input_cursor& operator=(any_input_cursor const &that) { if (&that != this) { this->~any_input_cursor(); ::new (static_cast<void*>(this)) any_input_cursor(that); } return *this; } ~any_input_cursor() { exec_(op::nuke, &data_, nullptr); } Reference read() const { return deref_(data_); } bool equal(any_input_cursor const &that) const { return exec_(op::comp, const_cast<blob*>(&data_), const_cast<blob*>(&that.data_)); } void next() { exec_(op::bump, &data_, nullptr); } }; } template<class Reference, class ValueType = std::remove_cv_t<std::remove_reference_t<Reference>>> using any_input_iterator = ranges::basic_iterator< any_iterator_detail::any_input_cursor<Reference, ValueType>>;
The text was updated successfully, but these errors were encountered:
TODO: Add iter_move support.
iter_move
Sorry, something went wrong.
No branches or pull requests
I'll just leave this here. Caveat: largely untested and probably buggy as hell.
The text was updated successfully, but these errors were encountered: