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)
DestRootDebug=$$BuildRoot/out/debug
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
}
################################
# Workaround vcproj generator subdirs
################################
lessThan(QT_MINOR_VERSION, 6) {
in_full_qmake: include(vcsubdirs.pri)
}
################################
# Black libs
################################

View File

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

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
#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"

View File

@@ -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<const typename C::iterator *>(pos.getImpl()))); }
//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 { while (it1 != it2) { it1 = iterator::fromImpl(m_impl.erase(*static_cast<const typename C::iterator *>(it1.getImpl()))); } return it1; }
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(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(it1.template getImpl<const typename C::iterator>())); } 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<const C *>(other.impl()) : size() == other.size() && std::equal(begin(), end(), other.begin()); }

View File

@@ -20,6 +20,7 @@
#include <type_traits>
#include <iterator>
#include <utility>
#include <typeindex>
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 <typename U> U &getImpl() { pimpl()->assertType(typeid(std::decay_t<U>)); return *static_cast<U*>(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 I> 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<const Pimpl&>(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 <typename U> U &getImpl() { pimpl()->assertType(typeid(std::decay_t<U>)); return *static_cast<U*>(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 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 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 <typename U> U &getImpl() { pimpl()->assertType(typeid(std::decay_t<U>)); return *static_cast<U*>(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 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 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;
};

View File

@@ -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<DisabledForJson>())
attr(o.m_array)
))
Q_DECLARE_METATYPE(BlackMisc::CPixmap)

View File

@@ -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 <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;
/*!
@@ -201,8 +190,7 @@ namespace BlackMisc
//! @}
//! 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 &&
std::is_convertible<value_type, typename T::value_type>::value>::type>
template <class T, class = std::enable_if_t<std::is_convertible<value_type, typename T::value_type>::value>>
operator T() const
{
T container;

View File

@@ -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<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(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<const typename C::iterator *>(pos.getImpl()))); }
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 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(it1.template getImpl<const typename C::iterator>(), it2.template getImpl<const typename C::iterator>())); }
void *impl() override { return &m_impl; }
private:
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 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 <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>();
return fromTaskImpl(owner, name, typeId, [task]() { return CVariant::fromResultOf(task); });
int typeId = qMetaTypeId<std::decay_t<decltype(std::forward<F>(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.

View File

@@ -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;

View File

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

View File

@@ -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 <QtTest/QtTest>
namespace BlackCoreTest

View File

@@ -109,13 +109,10 @@ using CNotHashableMapDictionary = BlackMisc::CDictionary<BlackMisc::CNotHashable
Q_DECLARE_METATYPE(CValueObjectDictionary)
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,
"Expected CValueObjectDictionary to use QHash");
static_assert(std::is_same<CNotHashableDictionary::impl_type, CNotHashableMapDictionary::impl_type>::value,
"Expected CDictionary<CNotHashableDictionary, Value> to use QMap");
#endif // ! Q_CC_MSVC
//! \endcond