refs #624 Removed many workarounds, no longer needed.

This commit is contained in:
Mathew Sutcliffe
2016-03-20 21:59:20 +00:00
parent 187501bb3c
commit a895cc2c54
15 changed files with 23 additions and 121 deletions

View File

@@ -2,4 +2,3 @@ SourceRoot=$$PWD
BuildRoot=$$shadowed($$SourceRoot) BuildRoot=$$shadowed($$SourceRoot)
DestRootDebug=$$BuildRoot/out/debug DestRootDebug=$$BuildRoot/out/debug
DestRootRelease=$$BuildRoot/out/release DestRootRelease=$$BuildRoot/out/release
CONFIG+=in_full_qmake

View File

@@ -15,14 +15,6 @@ macx:staticlib:isEmpty(SOURCES) {
QMAKE_MAC_SDK.$$basename(QMAKESPEC).$${QMAKE_MAC_SDK}.QMAKE_RANLIB = $$QMAKE_RANLIB 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 # Black libs
################################ ################################

View File

@@ -119,7 +119,7 @@ isEmpty(EXTERNALSROOT) {
EXTERNALSROOT = $$SourceRoot/externals EXTERNALSROOT = $$SourceRoot/externals
} }
!exists("$$EXTERNALSROOT/common/include"):in_full_qmake { !exists("$$EXTERNALSROOT/common/include") {
error("Could not find externals in $${EXTERNALSROOT}. Please install them!") error("Could not find externals in $${EXTERNALSROOT}. Please install them!")
} }

View File

@@ -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)
}

View File

@@ -13,7 +13,6 @@
#define BLACKGUI_COLUMNS_H #define BLACKGUI_COLUMNS_H
#include "blackgui/blackguiexport.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/collection.h"
#include "blackmisc/propertyindex.h" #include "blackmisc/propertyindex.h"
#include "columnformatters.h" #include "columnformatters.h"

View File

@@ -429,9 +429,9 @@ namespace BlackMisc
void clear() override { m_impl.clear(); } void clear() override { m_impl.clear(); }
iterator insert(const T &value) override { return iterator::fromImpl(insertHelper(m_impl.insert(value))); } 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 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<const typename C::iterator *>(pos.getImpl()))); } iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(pos.template getImpl<const typename C::iterator>())); }
//iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(*static_cast<const typename C::iterator *>(it1.getImpl()), *static_cast<const typename C::iterator*>(it2.getImpl()))); } //iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(it1.template getImpl<const typename C::iterator>(), it2.template getImpl<const typename C::iterator>())); }
iterator erase(iterator it1, iterator it2) override { while (it1 != it2) { it1 = iterator::fromImpl(m_impl.erase(*static_cast<const typename C::iterator *>(it1.getImpl()))); } return it1; } iterator erase(iterator it1, iterator it2) override { while (it1 != it2) { it1 = iterator::fromImpl(m_impl.erase(it1.template getImpl<const typename C::iterator>())); } return it1; }
iterator find(const T &value) override { return iterator::fromImpl(m_impl.find(value)); } 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)); } 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<const C *>(other.impl()) : size() == other.size() && std::equal(begin(), end(), other.begin()); } bool operator ==(const PimplBase &other) const override { return implType() == other.implType() ? m_impl == *static_cast<const C *>(other.impl()) : size() == other.size() && std::equal(begin(), end(), other.begin()); }

View File

@@ -20,6 +20,7 @@
#include <type_traits> #include <type_traits>
#include <iterator> #include <iterator>
#include <utility> #include <utility>
#include <typeindex>
namespace BlackMisc namespace BlackMisc
{ {
@@ -393,9 +394,8 @@ namespace BlackMisc
/*! /*!
* \brief Return opaque pointer to underlying implementation iterator object. * \brief Return opaque pointer to underlying implementation iterator object.
* \pre The iterator must have been initialized. * \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 <typename U> U &getImpl() { pimpl()->assertType(typeid(std::decay_t<U>)); return *static_cast<U*>(pimpl()->impl()); }
private: private:
class PimplBase class PimplBase
@@ -408,6 +408,7 @@ namespace BlackMisc
virtual void operator +=(difference_type) = 0; virtual void operator +=(difference_type) = 0;
virtual bool operator ==(const PimplBase &) const = 0; virtual bool operator ==(const PimplBase &) const = 0;
virtual void *impl() = 0; virtual void *impl() = 0;
virtual void assertType(std::type_index) const = 0;
}; };
template <class I> class Pimpl : public PimplBase template <class I> class Pimpl : public PimplBase
@@ -422,6 +423,7 @@ namespace BlackMisc
virtual void operator +=(difference_type n) override { std::advance(m_impl, n); } 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<const Pimpl&>(other).m_impl; } virtual bool operator ==(const PimplBase &other) const override { return m_impl == static_cast<const Pimpl&>(other).m_impl; }
virtual void *impl() override { return &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: private:
I m_impl; I m_impl;
}; };
@@ -586,9 +588,8 @@ namespace BlackMisc
/*! /*!
* \brief Return opaque pointer to underlying implementation iterator object. * \brief Return opaque pointer to underlying implementation iterator object.
* \pre The iterator must have been initialized. * \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 <typename U> U &getImpl() { pimpl()->assertType(typeid(std::decay_t<U>)); return *static_cast<U*>(pimpl()->impl()); }
private: private:
class PimplBase class PimplBase
@@ -608,6 +609,7 @@ namespace BlackMisc
virtual bool operator <=(const PimplBase &) const = 0; virtual bool operator <=(const PimplBase &) const = 0;
virtual bool operator >=(const PimplBase &) const = 0; virtual bool operator >=(const PimplBase &) const = 0;
virtual void *impl() = 0; virtual void *impl() = 0;
virtual void assertType(std::type_index) const = 0;
}; };
template <class I> class Pimpl : public PimplBase template <class I> class Pimpl : public PimplBase
@@ -629,6 +631,7 @@ namespace BlackMisc
virtual bool operator <=(const PimplBase &other) const override { return m_impl <= static_cast<const Pimpl&>(other).m_impl; } virtual bool operator <=(const PimplBase &other) const override { return m_impl <= static_cast<const Pimpl&>(other).m_impl; }
virtual bool operator >=(const PimplBase &other) const override { return m_impl >= static_cast<const Pimpl&>(other).m_impl; } virtual bool operator >=(const PimplBase &other) const override { return m_impl >= static_cast<const Pimpl&>(other).m_impl; }
virtual void *impl() override { return &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: private:
I m_impl; I m_impl;
}; };
@@ -805,9 +808,8 @@ namespace BlackMisc
/*! /*!
* \brief Return opaque pointer to underlying implementation iterator object. * \brief Return opaque pointer to underlying implementation iterator object.
* \pre The iterator must have been initialized. * \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 <typename U> U &getImpl() { pimpl()->assertType(typeid(std::decay_t<U>)); return *static_cast<U*>(pimpl()->impl()); }
private: private:
class PimplBase class PimplBase
@@ -828,6 +830,7 @@ namespace BlackMisc
virtual bool operator <=(const PimplBase &) const = 0; virtual bool operator <=(const PimplBase &) const = 0;
virtual bool operator >=(const PimplBase &) const = 0; virtual bool operator >=(const PimplBase &) const = 0;
virtual void *impl() = 0; virtual void *impl() = 0;
virtual void assertType(std::type_index) const = 0;
}; };
template <class I> class Pimpl : public PimplBase template <class I> class Pimpl : public PimplBase
@@ -850,6 +853,7 @@ namespace BlackMisc
virtual bool operator <=(const PimplBase &other) const override { return m_impl <= static_cast<const Pimpl&>(other).m_impl; } virtual bool operator <=(const PimplBase &other) const override { return m_impl <= static_cast<const Pimpl&>(other).m_impl; }
virtual bool operator >=(const PimplBase &other) const override { return m_impl >= static_cast<const Pimpl&>(other).m_impl; } virtual bool operator >=(const PimplBase &other) const override { return m_impl >= static_cast<const Pimpl&>(other).m_impl; }
virtual void *impl() override { return &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: private:
I m_impl; I m_impl;
}; };

View File

@@ -64,9 +64,8 @@ namespace BlackMisc
}; };
} // namespace } // namespace
//! \todo remove flags when gcc 4.7 streaming issue is resolved
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CPixmap, ( BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CPixmap, (
attr(o.m_array, flags<DisabledForJson>()) attr(o.m_array)
)) ))
Q_DECLARE_METATYPE(BlackMisc::CPixmap) Q_DECLARE_METATYPE(BlackMisc::CPixmap)

View File

@@ -25,17 +25,6 @@
namespace BlackMisc 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 <class T> struct is_initializer_list : public std::false_type {};
//! \private
template <class T> struct is_initializer_list<std::initializer_list<T>> : public std::true_type {};
}
template <class> class CRange; template <class> class CRange;
/*! /*!
@@ -201,8 +190,7 @@ namespace BlackMisc
//! @} //! @}
//! Implicit conversion to any container of value_type which supports push_back. This will copy elements. //! Implicit conversion to any container of value_type which supports push_back. This will copy elements.
template <class T, class = typename std::enable_if<! Private::is_initializer_list<T>::value && template <class T, class = std::enable_if_t<std::is_convertible<value_type, typename T::value_type>::value>>
std::is_convertible<value_type, typename T::value_type>::value>::type>
operator T() const operator T() const
{ {
T container; T container;

View File

@@ -693,12 +693,12 @@ namespace BlackMisc
size_type size() const override { return m_impl.size(); } size_type size() const override { return m_impl.size(); }
bool empty() const override { return m_impl.empty(); } bool empty() const override { return m_impl.empty(); }
void clear() override { m_impl.clear(); } void clear() override { m_impl.clear(); }
iterator insert(iterator pos, const T &value) override { return iterator::fromImpl(m_impl.insert(*static_cast<const typename C::iterator *>(pos.getImpl()), value)); } iterator insert(iterator pos, const T &value) override { return iterator::fromImpl(m_impl.insert(pos.template getImpl<const typename C::iterator>(), value)); }
void push_back(const T &value) override { m_impl.push_back(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 push_back(T &&value) override { m_impl.push_back(std::move(value)); }
void pop_back() override { m_impl.pop_back(); } void pop_back() override { m_impl.pop_back(); }
iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(*static_cast<const typename C::iterator *>(pos.getImpl()))); } iterator erase(iterator pos) override { return iterator::fromImpl(m_impl.erase(pos.template getImpl<const typename C::iterator>())); }
iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(*static_cast<const typename C::iterator *>(it1.getImpl()), *static_cast<const typename C::iterator *>(it2.getImpl()))); } iterator erase(iterator it1, iterator it2) override { return iterator::fromImpl(m_impl.erase(it1.template getImpl<const typename C::iterator>(), it2.template getImpl<const typename C::iterator>())); }
void *impl() override { return &m_impl; } void *impl() override { return &m_impl; }
private: private:
C m_impl; C m_impl;

View File

@@ -225,13 +225,12 @@ namespace BlackMisc
* \param owner Will be the parent of the new thread (the worker has no parent). * \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 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. * \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 <typename F> template <typename F>
static CWorker *fromTask(QObject *owner, const QString &name, F task) static CWorker *fromTask(QObject *owner, const QString &name, F &&task)
{ {
int typeId = qMetaTypeId<typename std::decay<decltype(task())>::type>(); int typeId = qMetaTypeId<std::decay_t<decltype(std::forward<F>(task)())>>();
return fromTaskImpl(owner, name, typeId, [task]() { return CVariant::fromResultOf(task); }); return fromTaskImpl(owner, name, typeId, [task = std::forward<F>(task)]() { return CVariant::fromResultOf(std::move(task)); });
} }
//! Connects to a functor to which will be passed the result when the task is finished. //! Connects to a functor to which will be passed the result when the task is finished.

View File

@@ -28,11 +28,7 @@ namespace XBus
struct CMessage struct CMessage
{ {
//! Constructor. //! Constructor.
CMessage(const std::string &text, float r, float g, float b) : m_text(text) CMessage(const std::string &text, float r, float g, float b) : m_text(text), m_rgb{{ r, g, b }} {}
{
// MSVC initializer list bug
std::tie(m_rgb[0], m_rgb[1], m_rgb[2]) = std::tie(r, g, b);
}
//! Text. //! Text.
std::string m_text; std::string m_text;

View File

@@ -17,7 +17,6 @@
* \ingroup testblackcore * \ingroup testblackcore
*/ */
#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue
#include <QtTest/QtTest> #include <QtTest/QtTest>
namespace BlackCoreTest namespace BlackCoreTest

View File

@@ -17,7 +17,6 @@
#ifndef BLACKCORETEST_TESTMAIN_H #ifndef BLACKCORETEST_TESTMAIN_H
#define BLACKCORETEST_TESTMAIN_H #define BLACKCORETEST_TESTMAIN_H
#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue
#include <QtTest/QtTest> #include <QtTest/QtTest>
namespace BlackCoreTest namespace BlackCoreTest

View File

@@ -109,13 +109,10 @@ using CNotHashableMapDictionary = BlackMisc::CDictionary<BlackMisc::CNotHashable
Q_DECLARE_METATYPE(CValueObjectDictionary) Q_DECLARE_METATYPE(CValueObjectDictionary)
Q_DECLARE_METATYPE(CNotHashableDictionary) Q_DECLARE_METATYPE(CNotHashableDictionary)
// MSVC has trouble with these checks
#if !defined(Q_CC_MSVC)
static_assert(std::is_same<CValueObjectDictionary::impl_type, CValueObjectHashDictionary::impl_type>::value, static_assert(std::is_same<CValueObjectDictionary::impl_type, CValueObjectHashDictionary::impl_type>::value,
"Expected CValueObjectDictionary to use QHash"); "Expected CValueObjectDictionary to use QHash");
static_assert(std::is_same<CNotHashableDictionary::impl_type, CNotHashableMapDictionary::impl_type>::value, static_assert(std::is_same<CNotHashableDictionary::impl_type, CNotHashableMapDictionary::impl_type>::value,
"Expected CDictionary<CNotHashableDictionary, Value> to use QMap"); "Expected CDictionary<CNotHashableDictionary, Value> to use QMap");
#endif // ! Q_CC_MSVC
//! \endcond //! \endcond