mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-04 16:56:53 +08:00
preparatory to refs #230, need to replace QSet with QOrderedSet
(which is our own custom class) in order to support standard algorithms. This also means adding generic comparison operators for CValueObject.
This commit is contained in:
@@ -22,7 +22,21 @@ namespace BlackMisc
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief Generic type-erased unsequenced container with value semantics.
|
||||
* Needed for compatibility with C++ standard algorithms which expect ordered sets.
|
||||
*/
|
||||
template <class T>
|
||||
class QOrderedSet : public QMap<T, T>
|
||||
{
|
||||
public:
|
||||
//! Type of values stored in the set.
|
||||
typedef T value_type;
|
||||
|
||||
//! Insert a new value into the set.
|
||||
typename QMap<T, T>::iterator insert(const T &value) { return QMap<T, T>::insert(value, value); }
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Generic type-erased ordered container with value semantics.
|
||||
* \tparam T the type of elements contained.
|
||||
*
|
||||
* Can take any suitable container class as its implementation at runtime.
|
||||
@@ -48,7 +62,7 @@ namespace BlackMisc
|
||||
/*!
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
CCollection() : m_pimpl(new Pimpl<QSet<T>>(QSet<T>())) {}
|
||||
CCollection() : m_pimpl(new Pimpl<QOrderedSet<T>>(QOrderedSet<T>())) {}
|
||||
|
||||
/*!
|
||||
* \brief Copy constructor.
|
||||
@@ -286,7 +300,7 @@ namespace BlackMisc
|
||||
bool operator ==(const PimplBase &other) const override { Pimpl copy = C(); for (auto i = other.cbegin(); i != other.cend(); ++i) copy.insert(*i); return m_impl == copy.m_impl; }
|
||||
private:
|
||||
C m_impl;
|
||||
// insertHelper: QSet::insert returns an iterator, but std::set::insert returns a std::pair<interator, bool>
|
||||
// insertHelper: QOrderedSet::insert returns an iterator, but std::set::insert returns a std::pair<interator, bool>
|
||||
template <class I> static I insertHelper(I i) { return i; }
|
||||
template <class I> static I insertHelper(std::pair<I, bool> p) { return p.first; }
|
||||
};
|
||||
@@ -307,6 +321,6 @@ Q_DECLARE_METATYPE(BlackMisc::CCollection<int>)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CCollection<uint>)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CCollection<qlonglong>)
|
||||
Q_DECLARE_METATYPE(BlackMisc::CCollection<qulonglong>)
|
||||
// CCollection<double> not instantiated because QSet<double> is not supported due to hashing constraints
|
||||
// CCollection<double> not instantiated due to it being a dumb idea because of rounding issues
|
||||
|
||||
#endif // guard
|
||||
|
||||
@@ -21,6 +21,25 @@ namespace BlackMisc
|
||||
// forward declaration
|
||||
class CIndexVariantMap;
|
||||
|
||||
namespace PhysicalQuantities
|
||||
{
|
||||
template <class MU, class PQ> class CPhysicalQuantity; // forward declaration
|
||||
|
||||
//! Traits class to test whether a class is a physical quantity class. Useful for enable_if.
|
||||
template <class T>
|
||||
class IsQuantity
|
||||
{
|
||||
struct yes { char x; };
|
||||
struct no { yes x[2]; };
|
||||
template <class MU, class PQ> static yes test(const CPhysicalQuantity<MU, PQ> &);
|
||||
static no test(...);
|
||||
|
||||
public:
|
||||
//! True if and only if T is derived from CPhysicalQuantity.
|
||||
static const bool value = sizeof(test(*(T*)0)) == sizeof(yes);
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Base class for value objects.
|
||||
* Public non-virtual interface with protected virtual implementation.
|
||||
@@ -81,6 +100,42 @@ namespace BlackMisc
|
||||
//! Operator != with value map
|
||||
friend bool operator!=(const CValueObject &valueObject, const CIndexVariantMap &valueMap);
|
||||
|
||||
//! Comparison operator to allow valueobjects be used as keys in QMap and std::set.
|
||||
template <class T> friend typename std::enable_if<std::is_base_of<CValueObject, T>::value && ! PhysicalQuantities::IsQuantity<T>::value, bool>::type
|
||||
operator<(const T &lhs, const T &rhs)
|
||||
{
|
||||
const auto &lhsBase = static_cast<const CValueObject &>(lhs);
|
||||
const auto &rhsBase = static_cast<const CValueObject &>(rhs);
|
||||
return lhsBase.compareImpl(rhsBase) < 0;
|
||||
}
|
||||
|
||||
//! Comparison for symmetry with operator<.
|
||||
template <class T> friend typename std::enable_if<std::is_base_of<CValueObject, T>::value && ! PhysicalQuantities::IsQuantity<T>::value, bool>::type
|
||||
operator>(const T &lhs, const T &rhs)
|
||||
{
|
||||
const auto &lhsBase = static_cast<const CValueObject &>(lhs);
|
||||
const auto &rhsBase = static_cast<const CValueObject &>(rhs);
|
||||
return lhsBase.compareImpl(rhsBase) > 0;
|
||||
}
|
||||
|
||||
//! Comparison for symmetry with operator<.
|
||||
template <class T> friend typename std::enable_if<std::is_base_of<CValueObject, T>::value && ! PhysicalQuantities::IsQuantity<T>::value, bool>::type
|
||||
operator<=(const T &lhs, const T &rhs)
|
||||
{
|
||||
const auto &lhsBase = static_cast<const CValueObject &>(lhs);
|
||||
const auto &rhsBase = static_cast<const CValueObject &>(rhs);
|
||||
return lhsBase.compareImpl(rhsBase) <= 0;
|
||||
}
|
||||
|
||||
//! Comparison for symmetry with operator<.
|
||||
template <class T> friend typename std::enable_if<std::is_base_of<CValueObject, T>::value && ! PhysicalQuantities::IsQuantity<T>::value, bool>::type
|
||||
operator>=(const T &lhs, const T &rhs)
|
||||
{
|
||||
const auto &lhsBase = static_cast<const CValueObject &>(lhs);
|
||||
const auto &rhsBase = static_cast<const CValueObject &>(rhs);
|
||||
return lhsBase.compareImpl(rhsBase) >= 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Compares two instances of related classes
|
||||
* and returns an integer less than, equal to, or greater than zero
|
||||
|
||||
Reference in New Issue
Block a user