diff --git a/.qmake.conf b/.qmake.conf index 738d1e5c9..9e677d28a 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -2,4 +2,3 @@ SourceRoot=$$PWD BuildRoot=$$shadowed($$SourceRoot) DestRootDebug=$$BuildRoot/out/debug DestRootRelease=$$BuildRoot/out/release -CONFIG+=in_full_qmake diff --git a/mkspecs/features/common_post.prf b/mkspecs/features/common_post.prf index 068bbd04c..01ecb0d5b 100644 --- a/mkspecs/features/common_post.prf +++ b/mkspecs/features/common_post.prf @@ -15,14 +15,6 @@ macx:staticlib:isEmpty(SOURCES) { QMAKE_MAC_SDK.$$basename(QMAKESPEC).$${QMAKE_MAC_SDK}.QMAKE_RANLIB = $$QMAKE_RANLIB } -################################ -# Workaround vcproj generator subdirs -################################ - -lessThan(QT_MINOR_VERSION, 6) { - in_full_qmake: include(vcsubdirs.pri) -} - ################################ # Black libs ################################ diff --git a/mkspecs/features/common_pre.prf b/mkspecs/features/common_pre.prf index 5f07ed4c8..aef08a06b 100644 --- a/mkspecs/features/common_pre.prf +++ b/mkspecs/features/common_pre.prf @@ -119,7 +119,7 @@ isEmpty(EXTERNALSROOT) { EXTERNALSROOT = $$SourceRoot/externals } -!exists("$$EXTERNALSROOT/common/include"):in_full_qmake { +!exists("$$EXTERNALSROOT/common/include") { error("Could not find externals in $${EXTERNALSROOT}. Please install them!") } diff --git a/mkspecs/features/vcsubdirs.pri b/mkspecs/features/vcsubdirs.pri deleted file mode 100644 index dc7c347ca..000000000 --- a/mkspecs/features/vcsubdirs.pri +++ /dev/null @@ -1,69 +0,0 @@ -# QMake generates an MSVC solution file for each SUBDIRS project, -# but we only want one solution file, so... - -# Test whether we are generating an MSVC solution file. -equals(TEMPLATE, "vcsubdirs") { - - # subdirToProjectFile(subdir, basedir) - # This function returns the absolute path of the .pro file referenced by subdir. - # \param subdir Any value which is valid to appear in the SUBDIRS variable. - # \param basedir The absolute directory of the .pro file containing the SUBDIRS variable. - # \param profile The .pro file containing the SUBDIRS variable (empty if it is this very project). - defineReplace(subdirToProjectFile) { - SUBDIR = $$1 - BASEDIR = $$2 - PROFILE = $$3 - BASENAME = $$basename(SUBDIR) - SUFFIX = $$section(SUBDIR, ".", -1, -1) - isEmpty(PROFILE) { - file = $$eval($${SUBDIR}.file) - subdir = $$eval($${SUBDIR}.subdir) - } - else { - file = $$fromfile($$PROFILE, $${SUBDIR}.file) - subdir = $$fromfile($$PROFILE, $${SUBDIR}.subdir) - } - !isEmpty(file): return($$BASEDIR/$$file) - !isEmpty(subdir): return($$BASEDIR/$$subdir/$${BASENAME}.pro) - equals(SUFFIX, "pro"): return($$BASEDIR/$$SUBDIR) - else: return($$BASEDIR/$$SUBDIR/$${BASENAME}.pro) - } - - # flattenSubdirs(subdirs, basedir) - # This function returns its subdirs argument, but when it sees a reference to a project - # which is itself a subdirs project, it is replaced with the SUBDIRS variable from that - # project, recursively. - # \param subdirs The value of a SUBDIRS variable. - # \param basedir The absolute directory of the .pro file containing the SUBDIRS variable. - # \param profile The .pro file containing the SUBDIRS variable (empty if it is this very project). - defineReplace(flattenSubdirs) { - SUBDIRS = $$1 - BASEDIR = $$2 - PROFILE = $$3 - for(subdir, SUBDIRS) { - SUBDIR_PROJECT = $$subdirToProjectFile($$subdir, $$BASEDIR, $$PROFILE) - INNER_REQUIRES = $$fromfile($$SUBDIR_PROJECT, REQUIRES) - REQUIRES_OK = 1 - for(req, INNER_REQUIRES): !if($${req}): REQUIRES_OK = 0 - equals(REQUIRES_OK,1) { - INNER_TEMPLATE = $$fromfile($$SUBDIR_PROJECT, TEMPLATE) - equals(INNER_TEMPLATE, "vcsubdirs") { - INNER_SUBDIRS = $$fromfile($$SUBDIR_PROJECT, SUBDIRS) - SUBDIRS_FLAT += $$flattenSubdirs($$INNER_SUBDIRS, $$dirname(SUBDIR_PROJECT), $$SUBDIR_PROJECT) - } - else: SUBDIRS_FLAT += $$SUBDIR_PROJECT - } - } - return($$SUBDIRS_FLAT) - } - - # Make sure we are in the top-level SUBDIRS project. - !equals(_PRO_FILE_PWD_, $$SourceRoot): error(This line should never be reached) - - # Recursively replace nested SUBDIRS with the leaves of their subtrees. - SUBDIRS = $$flattenSubdirs($$SUBDIRS, $$_PRO_FILE_PWD_) - - # Remove duplicates, because qmake. - SUBDIRS = $$unique(SUBDIRS) - -} diff --git a/src/blackgui/models/columns.h b/src/blackgui/models/columns.h index 19ed1fa6e..9fc3e705a 100644 --- a/src/blackgui/models/columns.h +++ b/src/blackgui/models/columns.h @@ -13,7 +13,6 @@ #define BLACKGUI_COLUMNS_H #include "blackgui/blackguiexport.h" -#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue #include "blackmisc/collection.h" #include "blackmisc/propertyindex.h" #include "columnformatters.h" diff --git a/src/blackmisc/collection.h b/src/blackmisc/collection.h index de3ff4475..b82e15f85 100644 --- a/src/blackmisc/collection.h +++ b/src/blackmisc/collection.h @@ -429,9 +429,9 @@ namespace BlackMisc 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; } + iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(pos.template getImpl())); } + //iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(it1.template getImpl(), it2.template getImpl())); } + iterator erase(iterator it1, iterator it2) override { while (it1 != it2) { it1 = iterator::fromImpl(m_impl.erase(it1.template getImpl())); } return it1; } iterator find(const T &value) override { return iterator::fromImpl(m_impl.find(value)); } const_iterator find(const T &value) const override { return const_iterator::fromImpl(m_impl.find(value)); } bool operator ==(const PimplBase &other) const override { return implType() == other.implType() ? m_impl == *static_cast(other.impl()) : size() == other.size() && std::equal(begin(), end(), other.begin()); } diff --git a/src/blackmisc/iterator.h b/src/blackmisc/iterator.h index aea6294ef..85e3d8b2b 100644 --- a/src/blackmisc/iterator.h +++ b/src/blackmisc/iterator.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace BlackMisc { @@ -393,9 +394,8 @@ namespace BlackMisc /*! * \brief Return opaque pointer to underlying implementation iterator object. * \pre The iterator must have been initialized. - * \todo Returning by void* is rotten, but GCC gives a very cryptic error if I make it a function template with a cast inside. */ - void *getImpl() { return pimpl()->impl(); } + template U &getImpl() { pimpl()->assertType(typeid(std::decay_t)); return *static_cast(pimpl()->impl()); } private: class PimplBase @@ -408,6 +408,7 @@ namespace BlackMisc virtual void operator +=(difference_type) = 0; virtual bool operator ==(const PimplBase &) const = 0; virtual void *impl() = 0; + virtual void assertType(std::type_index) const = 0; }; template class Pimpl : public PimplBase @@ -422,6 +423,7 @@ namespace BlackMisc virtual void operator +=(difference_type n) override { std::advance(m_impl, n); } virtual bool operator ==(const PimplBase &other) const override { return m_impl == static_cast(other).m_impl; } virtual void *impl() override { return &m_impl; } + virtual void assertType(std::type_index ti) const override { Q_ASSERT(ti == typeid(I)); Q_UNUSED(ti); } private: I m_impl; }; @@ -586,9 +588,8 @@ namespace BlackMisc /*! * \brief Return opaque pointer to underlying implementation iterator object. * \pre The iterator must have been initialized. - * \todo Returning by void* is rotten, but GCC gives a very cryptic error if I make it a function template with a cast inside. */ - void *getImpl() { return pimpl()->impl(); } + template U &getImpl() { pimpl()->assertType(typeid(std::decay_t)); return *static_cast(pimpl()->impl()); } private: class PimplBase @@ -608,6 +609,7 @@ namespace BlackMisc virtual bool operator <=(const PimplBase &) const = 0; virtual bool operator >=(const PimplBase &) const = 0; virtual void *impl() = 0; + virtual void assertType(std::type_index) const = 0; }; template class Pimpl : public PimplBase @@ -629,6 +631,7 @@ namespace BlackMisc virtual bool operator <=(const PimplBase &other) const override { return m_impl <= static_cast(other).m_impl; } virtual bool operator >=(const PimplBase &other) const override { return m_impl >= static_cast(other).m_impl; } virtual void *impl() override { return &m_impl; } + virtual void assertType(std::type_index ti) const override { Q_ASSERT(ti == typeid(I)); Q_UNUSED(ti); } private: I m_impl; }; @@ -805,9 +808,8 @@ namespace BlackMisc /*! * \brief Return opaque pointer to underlying implementation iterator object. * \pre The iterator must have been initialized. - * \todo Returning by void* is rotten, but GCC gives a very cryptic error if I make it a function template with a cast inside. */ - void *getImpl() { return pimpl()->impl(); } + template U &getImpl() { pimpl()->assertType(typeid(std::decay_t)); return *static_cast(pimpl()->impl()); } private: class PimplBase @@ -828,6 +830,7 @@ namespace BlackMisc virtual bool operator <=(const PimplBase &) const = 0; virtual bool operator >=(const PimplBase &) const = 0; virtual void *impl() = 0; + virtual void assertType(std::type_index) const = 0; }; template class Pimpl : public PimplBase @@ -850,6 +853,7 @@ namespace BlackMisc virtual bool operator <=(const PimplBase &other) const override { return m_impl <= static_cast(other).m_impl; } virtual bool operator >=(const PimplBase &other) const override { return m_impl >= static_cast(other).m_impl; } virtual void *impl() override { return &m_impl; } + virtual void assertType(std::type_index ti) const override { Q_ASSERT(ti == typeid(I)); Q_UNUSED(ti); } private: I m_impl; }; diff --git a/src/blackmisc/pixmap.h b/src/blackmisc/pixmap.h index df2b11648..bbe952e9b 100644 --- a/src/blackmisc/pixmap.h +++ b/src/blackmisc/pixmap.h @@ -64,9 +64,8 @@ namespace BlackMisc }; } // namespace -//! \todo remove flags when gcc 4.7 streaming issue is resolved BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CPixmap, ( - attr(o.m_array, flags()) + attr(o.m_array) )) Q_DECLARE_METATYPE(BlackMisc::CPixmap) diff --git a/src/blackmisc/range.h b/src/blackmisc/range.h index c008633a3..a234b6917 100644 --- a/src/blackmisc/range.h +++ b/src/blackmisc/range.h @@ -25,17 +25,6 @@ namespace BlackMisc { - namespace Private - { - // Trait to exclude std::initializer_list from the overload set of CRange conversion operators using SFINAE. - // Needed to workaround a bug in MSVC whereby it considers the copy constructor and initializer list constructor - // of a container to be ambiguous when converting from a CRange. - //! \private - template struct is_initializer_list : public std::false_type {}; - //! \private - template struct is_initializer_list> : public std::true_type {}; - } - template class CRange; /*! @@ -201,8 +190,7 @@ namespace BlackMisc //! @} //! Implicit conversion to any container of value_type which supports push_back. This will copy elements. - template ::value && - std::is_convertible::value>::type> + template ::value>> operator T() const { T container; diff --git a/src/blackmisc/sequence.h b/src/blackmisc/sequence.h index ffe39b49f..d9175bcb6 100644 --- a/src/blackmisc/sequence.h +++ b/src/blackmisc/sequence.h @@ -693,12 +693,12 @@ namespace BlackMisc size_type size() const override { return m_impl.size(); } bool empty() const override { return m_impl.empty(); } 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)); } + iterator insert(iterator pos, const T &value) override { return iterator::fromImpl(m_impl.insert(pos.template 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()))); } + iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(pos.template getImpl())); } + iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(it1.template getImpl(), it2.template getImpl())); } void *impl() override { return &m_impl; } private: C m_impl; diff --git a/src/blackmisc/worker.h b/src/blackmisc/worker.h index 0fd6fde16..e8735cf3f 100644 --- a/src/blackmisc/worker.h +++ b/src/blackmisc/worker.h @@ -225,13 +225,12 @@ namespace BlackMisc * \param owner Will be the parent of the new thread (the worker has no parent). * \param name A name for the task, which will be used to create a name for the thread. * \param task A function object which will be run by the worker in its thread. - * \todo An MSVC bug prevents perfect-forwarding of task. */ template - static CWorker *fromTask(QObject *owner, const QString &name, F task) + static CWorker *fromTask(QObject *owner, const QString &name, F &&task) { - int typeId = qMetaTypeId::type>(); - return fromTaskImpl(owner, name, typeId, [task]() { return CVariant::fromResultOf(task); }); + int typeId = qMetaTypeId(task)())>>(); + return fromTaskImpl(owner, name, typeId, [task = std::forward(task)]() { return CVariant::fromResultOf(std::move(task)); }); } //! Connects to a functor to which will be passed the result when the task is finished. diff --git a/src/xbus/messages.h b/src/xbus/messages.h index 258f46182..0a86b5bb4 100644 --- a/src/xbus/messages.h +++ b/src/xbus/messages.h @@ -28,11 +28,7 @@ namespace XBus struct CMessage { //! Constructor. - CMessage(const std::string &text, float r, float g, float b) : m_text(text) - { - // MSVC initializer list bug - std::tie(m_rgb[0], m_rgb[1], m_rgb[2]) = std::tie(r, g, b); - } + CMessage(const std::string &text, float r, float g, float b) : m_text(text), m_rgb{{ r, g, b }} {} //! Text. std::string m_text; diff --git a/tests/blackcore/testblackcoremain.h b/tests/blackcore/testblackcoremain.h index 871178ebd..8dfbd1a37 100644 --- a/tests/blackcore/testblackcoremain.h +++ b/tests/blackcore/testblackcoremain.h @@ -17,7 +17,6 @@ * \ingroup testblackcore */ -#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue #include namespace BlackCoreTest diff --git a/tests/blackgui/testblackguimain.h b/tests/blackgui/testblackguimain.h index edc5d5299..299c8b064 100644 --- a/tests/blackgui/testblackguimain.h +++ b/tests/blackgui/testblackguimain.h @@ -17,7 +17,6 @@ #ifndef BLACKCORETEST_TESTMAIN_H #define BLACKCORETEST_TESTMAIN_H -#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue #include namespace BlackCoreTest diff --git a/tests/blackmisc/testvalueobject.h b/tests/blackmisc/testvalueobject.h index 6155ae66c..602e4310d 100644 --- a/tests/blackmisc/testvalueobject.h +++ b/tests/blackmisc/testvalueobject.h @@ -109,13 +109,10 @@ using CNotHashableMapDictionary = BlackMisc::CDictionary::value, "Expected CValueObjectDictionary to use QHash"); static_assert(std::is_same::value, "Expected CDictionary to use QMap"); -#endif // ! Q_CC_MSVC //! \endcond