diff --git a/src/blackmisc/collection.h b/src/blackmisc/collection.h index 1fe81225b..72ca06dec 100644 --- a/src/blackmisc/collection.h +++ b/src/blackmisc/collection.h @@ -50,13 +50,6 @@ namespace BlackMisc */ CCollection() : m_pimpl(new Pimpl>(QSet())) {} - /*! - * \brief Constructor. - * \tparam C Becomes the collection's implementation type. - * \param c Initial value for the collection; typically empty, but could contain elements. - */ - template CCollection(C c) : m_pimpl(new Pimpl(std::move(c))) {} - /*! * \brief Copy constructor. * \param other @@ -69,13 +62,6 @@ namespace BlackMisc */ CCollection(CCollection &&other) : m_pimpl(other.m_pimpl.take()) {} - /*! - * \brief Assignment. - * \tparam C Becomes the collection's new implementation type. - * \param c New value for the collection; typically empty, but could contain elements. - */ - template CCollection &operator =(C c) { m_pimpl.reset(new Pimpl(std::move(c))); return *this; } - /*! * \brief Copy assignment. * \param other @@ -90,11 +76,19 @@ namespace BlackMisc */ CCollection &operator =(CCollection && other) { m_pimpl.reset(other.m_pimpl.take()); return *this; } + /*! + * \brief Create a new collection with a specific implementation type. + * \tparam C Becomes the collection's implementation type. + * \param c Initial value for the collection; default is empty, but it could contain elements if desired. The value is copied. + * \return + */ + 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. * \tparam C Becomes the collection's new implementation type. */ - template void changeImpl(C = C()) { CCollection c = C(); for (auto i = cbegin(); i != cend(); ++i) c.insert(*i); *this = std::move(c); } + template void changeImpl(C = C()) { auto c = fromImpl(C()); for (auto i = cbegin(); i != cend(); ++i) c.insert(*i); *this = std::move(c); } /*! * \brief Like changeImpl, but uses the implementation type of another collection. @@ -275,6 +269,8 @@ namespace BlackMisc typedef QScopedPointer PimplPtr; PimplPtr m_pimpl; + CCollection(PimplBase *pimpl) : m_pimpl(pimpl) {} // private ctor used by fromImpl() + // using these methods to access m_pimpl.data() eases the cognitive burden of correctly forwarding const PimplBase *pimpl() { return m_pimpl.data(); } const PimplBase *pimpl() const { return m_pimpl.data(); } diff --git a/src/blackmisc/sequence.h b/src/blackmisc/sequence.h index dbf724299..2fd7ca62d 100644 --- a/src/blackmisc/sequence.h +++ b/src/blackmisc/sequence.h @@ -50,13 +50,6 @@ namespace BlackMisc */ CSequence() : m_pimpl(new Pimpl>(QList())) {} - /*! - * \brief Constructor. - * \tparam C Becomes the sequence's implementation type. - * \param c Initial value for the sequence; typically empty, but could contain elements. - */ - template CSequence(C c) : m_pimpl(new Pimpl(std::move(c))) {} - /*! * \brief Copy constructor. * \param other @@ -69,13 +62,6 @@ namespace BlackMisc */ CSequence(CSequence &&other) : m_pimpl(other.m_pimpl.take()) {} - /*! - * \brief Assignment. - * \tparam C Becomes the sequence's new implementation type. - * \param c New value for the sequence; typically empty, but could contain elements. - */ - template CSequence &operator =(C c) { m_pimpl.reset(new Pimpl(std::move(c))); return *this; } - /*! * \brief Copy assignment. * \param other @@ -90,11 +76,19 @@ namespace BlackMisc */ CSequence &operator =(CSequence &&other) { m_pimpl.reset(other.m_pimpl.take()); return *this; } + /*! + * \brief Create a new sequence with a specific implementation type. + * \tparam C Becomes the sequence's implementation type. + * \param c Initial value for the sequence; default is empty, but it could contain elements if desired. The value is copied. + * \return + */ + 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. * \tparam C Becomes the sequence's new implementation type. */ - template void changeImpl(C = C()) { CSequence c = 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()); for (auto i = cbegin(); i != cend(); ++i) c.push_back(*i); *this = std::move(c); } /*! * \brief Like changeImpl, but uses the implementation type of another sequence. @@ -508,6 +502,8 @@ namespace BlackMisc typedef QScopedPointer PimplPtr; PimplPtr m_pimpl; + explicit CSequence(PimplBase *pimpl) : m_pimpl(pimpl) {} // private ctor used by fromImpl() + // using these methods to access m_pimpl.data() eases the cognitive burden of correctly forwarding const PimplBase *pimpl() { return m_pimpl.data(); } const PimplBase *pimpl() const { return m_pimpl.data(); } diff --git a/tests/blackmisc/testcontainers.cpp b/tests/blackmisc/testcontainers.cpp index cd9128d66..fbd73612c 100644 --- a/tests/blackmisc/testcontainers.cpp +++ b/tests/blackmisc/testcontainers.cpp @@ -3,9 +3,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "testcontainers.h" #include "blackmisc/collection.h" #include "blackmisc/sequence.h" -#include "testcontainers.h" #include #include #include @@ -19,7 +19,7 @@ namespace BlackMiscTest { CCollection c1; QVERIFY2(c1.empty(), "Uninitialized collection is empty"); - CCollection c2 = QList(); + auto c2 = CCollection::fromImpl(QList()); QVERIFY2(c1 == c2, "Uninitialized and empty collections are equal"); c1.changeImpl(std::vector()); QVERIFY2(c1 == c2, "Two empty collections are equal"); @@ -42,7 +42,7 @@ namespace BlackMiscTest { CSequence s1; QVERIFY2(s1.empty(), "Uninitialized sequence is empty"); - CSequence s2 = QList(); + auto s2 = CSequence::fromImpl(QList()); QVERIFY2(s1 == s2, "Uninitialized and empty sequence are equal"); s1.changeImpl(std::vector()); QVERIFY2(s1 == s2, "Two empty sequences are equal");