diff --git a/src/blackmisc/collection.h b/src/blackmisc/collection.h index 56e095a01..b32b04967 100644 --- a/src/blackmisc/collection.h +++ b/src/blackmisc/collection.h @@ -78,16 +78,16 @@ namespace BlackMisc template static CCollection fromImpl(C c = C()) { return CCollection(new Pimpl(std::move(c))); } /*! - * \brief Change the implementation type but keep all the same elements, by copying them into the new implementation. + * \brief Change the implementation type but keep all the same elements, by moving them into the new implementation. * \tparam C Becomes the collection's new implementation type. */ - template void changeImpl(C = C()) { auto c = fromImpl(C()); for (auto i = cbegin(); i != cend(); ++i) c.insert(*i); *this = std::move(c); } + template void changeImpl(C = C()) { auto c = fromImpl(C()); std::move(begin(), end(), std::inserter(c, c.begin())); *this = std::move(c); } /*! * \brief Like changeImpl, but uses the implementation type of another collection. * \pre The other collection must be initialized. */ - void useImplOf(const CCollection &other) { PimplPtr p = other.pimpl()->cloneEmpty(); for (auto i = cbegin(); i != cend(); ++i) p->insert(*i); m_pimpl.reset(p.take()); } + void useImplOf(const CCollection &other) { PimplPtr p = other.pimpl()->cloneEmpty(); std::move(begin(), end(), std::inserter(*p, p->begin())); m_pimpl.reset(p.take()); } /*! * \brief Returns iterator at the beginning of the collection. @@ -144,6 +144,22 @@ namespace BlackMisc */ void clear() { if (pimpl()) pimpl()->clear(); } + /*! + * \brief For compatibility with std::inserter. + * \param hint Ignored. + * \param value The value to insert. + * \pre The collection must be initialized. + */ + iterator insert(const_iterator hint, const T &value) { Q_UNUSED(hint); return insert(value); } + + /*! + * \brief For compatibility with std::inserter. + * \param hint Ignored. + * \param value The value to move in. + * \pre The collection must be initialized. + */ + iterator insert(const_iterator hint, T &&value) { insert(std::move(value)); Q_UNUSED(hint); } + /*! * \brief Inserts an element into the collection. * \return An iterator to the position where value was inserted. @@ -151,6 +167,13 @@ namespace BlackMisc */ iterator insert(const T &value) { Q_ASSERT(pimpl()); return pimpl()->insert(value); } + /*! + * \brief Moves an element into the collection. + * \return An iterator to the position where value was inserted. + * \pre The collection must be initialized. + */ + iterator insert(T &&value) { Q_ASSERT(pimpl()); return pimpl()->insert(std::move(value)); } + /*! * \brief Synonym for insert. * \return An iterator to the position where value was inserted. @@ -158,6 +181,13 @@ namespace BlackMisc */ iterator push_back(const T &value) { return insert(value); } + /*! + * \brief Synonym for insert. + * \return An iterator to the position where value was inserted. + * \pre The collection must be initialized. + */ + iterator push_back(T &&value) { return insert(std::move(value)); } + /*! * \brief Remove the element pointed to by the given iterator. * \return An iterator to the position of the next element after the one removed. @@ -222,6 +252,7 @@ namespace BlackMisc virtual bool empty() const = 0; virtual void clear() = 0; virtual iterator insert(const T &value) = 0; + virtual iterator insert(T &&value) = 0; virtual iterator erase(iterator pos) = 0; virtual iterator erase(iterator it1, iterator it2) = 0; virtual iterator find(const T &value) = 0; @@ -246,6 +277,7 @@ namespace BlackMisc bool empty() const override { return m_impl.empty(); } void clear() override { m_impl.clear(); } iterator insert(const T &value) override { return iterator::fromImpl(insertHelper(m_impl.insert(value))); } + iterator insert(T &&value) override { return iterator::fromImpl(insertHelper(m_impl.insert(std::move(value)))); } iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(*static_cast(pos.getImpl()))); } //iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(*static_cast(it1.getImpl()), *static_cast(it2.getImpl()))); } iterator erase(iterator it1, iterator it2) override { while (it1 != it2) { it1 = iterator::fromImpl(m_impl.erase(*static_cast(it1.getImpl()))); } return it1; } diff --git a/src/blackmisc/sequence.h b/src/blackmisc/sequence.h index 065e4f5ba..2ef33c65d 100644 --- a/src/blackmisc/sequence.h +++ b/src/blackmisc/sequence.h @@ -78,16 +78,16 @@ namespace BlackMisc template static CSequence fromImpl(C c = C()) { return CSequence(new Pimpl(std::move(c))); } /*! - * \brief Change the implementation type but keep all the same elements, by copying them into the new implementation. + * \brief Change the implementation type but keep all the same elements, by moving them into the new implementation. * \tparam C Becomes the sequence's new implementation type. */ - template void changeImpl(C = C()) { auto c = fromImpl(C()); for (auto i = cbegin(); i != cend(); ++i) c.push_back(*i); *this = std::move(c); } + template void changeImpl(C = C()) { auto c = fromImpl(C()); std::move(begin(), end(), std::inserter(c, c.begin())); *this = std::move(c); } /*! * \brief Like changeImpl, but uses the implementation type of another sequence. * \pre The other sequence must be initialized. */ - void useImplOf(const CSequence &other) { PimplPtr p = other.pimpl()->cloneEmpty(); for (auto i = cbegin(); i != cend(); ++i) p->push_back(*i); m_pimpl.reset(p.take()); } + void useImplOf(const CSequence &other) { PimplPtr p = other.pimpl()->cloneEmpty(); std::move(begin(), end(), std::inserter(*p, p->begin())); m_pimpl.reset(p.take()); } /*! * \brief Returns iterator at the beginning of the sequence. @@ -187,18 +187,37 @@ namespace BlackMisc */ iterator insert(iterator before, const T &value) { Q_ASSERT(pimpl()); return pimpl()->insert(before, value); } + /*! + * \brief Moves an element into the sequence. + * \return An iterator to the position where value was inserted. + * \pre The sequence must be initialized. + */ + iterator insert(iterator before, T &&value) { Q_ASSERT(pimpl()); return pimpl()->insert(before, std::move(value)); } + /*! * \brief Appends an element at the end of the sequence. * \pre The sequence must be initialized. */ void push_back(const T &value) { Q_ASSERT(pimpl()); pimpl()->push_back(value); } + /*! + * \brief Move-appends an element at the end of the sequence. + * \pre The sequence must be initialized. + */ + void push_back(T &&value) { Q_ASSERT(pimpl()); pimpl()->push_back(std::move(value)); } + /*! * \brief Synonym for push_back. * \pre The sequence must be initialized. */ void insert(const T &value) { push_back(value); } + /*! + * \brief Synonym for push_back. + * \pre The sequence must be initialized. + */ + void insert(T &&value) { push_back(std::move(value)); } + /*! * \brief Removes an element at the end of the sequence. * \pre The sequence must contain at least one element. @@ -450,6 +469,7 @@ namespace BlackMisc virtual void clear() = 0; virtual iterator insert(iterator pos, const T &value) = 0; virtual void push_back(const T &value) = 0; + virtual void push_back(T &&value) = 0; virtual void pop_back() = 0; virtual iterator erase(iterator pos) = 0; virtual iterator erase(iterator it1, iterator it2) = 0; @@ -480,6 +500,7 @@ namespace BlackMisc void clear() override { m_impl.clear(); } iterator insert(iterator pos, const T &value) override { return iterator::fromImpl(m_impl.insert(*static_cast(pos.getImpl()), value)); } void push_back(const T &value) override { m_impl.push_back(value); } + void push_back(T &&value) override { m_impl.push_back(std::move(value)); } void pop_back() override { m_impl.pop_back(); } iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(*static_cast(pos.getImpl()))); } iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(*static_cast(it1.getImpl()), *static_cast(it2.getImpl()))); }