Upgrade: simplify comparisons
Now able to remove most complicated comparison operators and most usages of boost::operators... In most cases it is sufficient just to define one ''spaceship operator'', and often even that one can be synthesised. However — we still use boost::operators for arithmetic types, notably the `lib::time::TimeValue`, which is addable and mutipliable
This commit is contained in:
parent
bad4827b34
commit
b6a39fa831
16 changed files with 507 additions and 169 deletions
|
|
@ -21,7 +21,7 @@
|
|||
**
|
||||
** This header is intended to be incorporated as part of the advice system implementation (advice.cpp).
|
||||
** It is \em not usable as an external interface. But it is written in a rather self-contained manner,
|
||||
** in order to be testable in isolation. To this end, the actual PointOfAdvice entities being organised
|
||||
** in order to be testable in isolation. To this end, the actual PointOfAdvice entities \a POA organised
|
||||
** by this index datastructure remain abstract (defined as template parameter), and are only manipulated
|
||||
** through the following functions:
|
||||
** - \c hash_value(POA)
|
||||
|
|
@ -87,7 +87,6 @@
|
|||
#include "lib/util.hpp"
|
||||
#include "common/advice/binding.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -122,6 +121,7 @@ namespace advice {
|
|||
* by invoking the \c setSolution() function on the
|
||||
* corresponding PointOfAdvice entity.
|
||||
*
|
||||
* @tparam POA _point-of-advice_ exposing a matcher and solution
|
||||
* @note element \em identity is defined in terms of pointing
|
||||
* to the same memory location of a POA (point of advice).
|
||||
* Thus e.g. #hasProvision means this index holds an entry
|
||||
|
|
@ -141,12 +141,8 @@ namespace advice {
|
|||
class Index
|
||||
{
|
||||
|
||||
|
||||
struct Entry
|
||||
: pair<Binding::Matcher, POA*>
|
||||
, boost::equality_comparable<Entry, POA,
|
||||
boost::equality_comparable<Entry>
|
||||
>
|
||||
{
|
||||
explicit
|
||||
Entry (POA& elm)
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <compare>
|
||||
#include <memory>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -136,6 +136,8 @@ namespace lumiera {
|
|||
: kind(k)
|
||||
, type(t)
|
||||
{ }
|
||||
|
||||
auto operator<=> (QueryID const&) const =default;
|
||||
};
|
||||
|
||||
QueryID const&
|
||||
|
|
@ -185,26 +187,6 @@ namespace lumiera {
|
|||
};
|
||||
|
||||
|
||||
inline bool
|
||||
operator< (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
||||
{
|
||||
return id1.kind < id2.kind
|
||||
or(id1.kind == id2.kind and id1.type < id2.type);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator== (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
||||
{
|
||||
return id1.kind == id2.kind
|
||||
and id1.type == id2.type;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!= (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
||||
{
|
||||
return not (id1 == id2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
|
@ -386,7 +368,6 @@ namespace lumiera {
|
|||
* Implicitly convertible to and from Query instances.
|
||||
*/
|
||||
class QueryKey
|
||||
: boost::totally_ordered<QueryKey>
|
||||
{
|
||||
Goal::QueryID id_;
|
||||
lib::QueryText def_;
|
||||
|
|
@ -442,21 +423,19 @@ namespace lumiera {
|
|||
}
|
||||
|
||||
|
||||
friend bool
|
||||
operator< (QueryKey const& q1, QueryKey const& q2)
|
||||
friend std::strong_ordering
|
||||
operator<=> (QueryKey const& q1, QueryKey const& q2)
|
||||
{
|
||||
uint d1 = q1.degree();
|
||||
uint d2 = q2.degree();
|
||||
return d1 < d2
|
||||
or(d1 == d2 and ( q1.def_ < q2.def_
|
||||
or (q1.def_ == q2.def_ and q1.id_ < q2.id_)));
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator== (QueryKey const& q1, QueryKey const& q2)
|
||||
{
|
||||
return q1.def_ == q2.def_;
|
||||
if (auto o1 = d1 <=> d2; o1 != 0)
|
||||
return o1;
|
||||
if (auto o2 = q1.def_ <=> q2.def_; o2 != 0)
|
||||
return o2;
|
||||
else
|
||||
return q1.id_ <=> q2.id_;
|
||||
}
|
||||
bool operator== (QueryKey const&) const =default;
|
||||
|
||||
friend size_t
|
||||
hash_value (QueryKey const& q)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
** @deprecated 10/2024 seems very likely that similar functionality moves down
|
||||
** into the render-engine implementation and will no longer be considered
|
||||
** a constituent of the public interface.
|
||||
** @todo 6/2025 basically everything here is unused or will likely be done
|
||||
** in a different way — expect this and rendergraph.cpp to be obsolete
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -31,7 +33,8 @@
|
|||
#define LUMIERA_FRAMEID_H
|
||||
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include "lib/integral.hpp"
|
||||
#include <compare>
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
|
|
@ -73,15 +76,14 @@ namespace lumiera {
|
|||
* later on define what is actually needed; this header should then
|
||||
* be replaced by a combined C/C++ header
|
||||
*/
|
||||
class FrameID : boost::totally_ordered<FrameID> ////////////TODO it seems we don't need total ordering, only comparison. Clarify this!
|
||||
class FrameID
|
||||
{
|
||||
long dummy;
|
||||
public:
|
||||
FrameID(long dum=0) : dummy(dum) {}
|
||||
operator long () { return dummy; }
|
||||
|
||||
bool operator< (const FrameID& other) const { return dummy < other.dummy; }
|
||||
bool operator== (const FrameID& other) const { return dummy == other.dummy; }
|
||||
auto operator<=> (FrameID const&) const =default;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <compare>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
|
@ -131,7 +131,6 @@ namespace idi {
|
|||
* for building a combined hash and symbolic ID.
|
||||
*/
|
||||
class BareEntryID
|
||||
: public boost::equality_comparable<BareEntryID>
|
||||
{
|
||||
|
||||
string symbol_;
|
||||
|
|
@ -217,7 +216,6 @@ namespace idi {
|
|||
template<class TY>
|
||||
struct EntryID
|
||||
: BareEntryID
|
||||
, boost::totally_ordered< EntryID<TY> >
|
||||
{
|
||||
|
||||
/** case-1: auto generated symbolic ID */
|
||||
|
|
@ -272,15 +270,17 @@ namespace idi {
|
|||
explicit
|
||||
operator string() const;
|
||||
|
||||
friend bool operator< (EntryID const& i1, EntryID const& i2) { return i1.getSym() < i2.getSym(); }
|
||||
friend auto operator<=> (EntryID const& i1, EntryID const& i2) { return i1.getSym() <=> i2.getSym(); }
|
||||
};
|
||||
|
||||
|
||||
inline bool
|
||||
operator== (BareEntryID const& i1, BareEntryID const& i2)
|
||||
{
|
||||
return i1.getHash() == i2.getHash();
|
||||
}
|
||||
// Note: since we allow comparison only between EntryIDs of same type
|
||||
// and also feed-down the symbol into the hash value, both equality
|
||||
// and (total) ordering mesh up perfectly.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ namespace lib {
|
|||
return definition_;
|
||||
}
|
||||
|
||||
auto operator<=> (QueryText const&) const =default;
|
||||
|
||||
bool
|
||||
empty() const
|
||||
|
|
@ -105,19 +106,6 @@ namespace lib {
|
|||
|
||||
private:
|
||||
string normalise (string const& rawDefinition);
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (QueryText const& q1, QueryText const& q2)
|
||||
{
|
||||
return q1.definition_ == q2.definition_;
|
||||
}
|
||||
friend bool
|
||||
operator< (QueryText const& q1, QueryText const& q2)
|
||||
{
|
||||
return q1.definition_ < q2.definition_;
|
||||
}
|
||||
|
||||
friend HashVal hash_value (QueryText const& entry);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
#include "lib/symbol.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
|
@ -215,7 +214,6 @@ namespace time {
|
|||
, class FMT = digxel::Formatter<NUM>
|
||||
>
|
||||
class Digxel
|
||||
: public boost::totally_ordered<Digxel<NUM,FMT>>
|
||||
{
|
||||
mutable
|
||||
FMT buffer_;
|
||||
|
|
@ -297,8 +295,8 @@ namespace time {
|
|||
NUM operator++ (int) { NUM p(value_); *this =p+1; return p;}
|
||||
NUM operator-- (int) { NUM p(value_); *this =p-1; return p;}
|
||||
|
||||
//---Supporting-totally_ordered---------
|
||||
bool operator< (Digxel const& o) const { return value_ < NUM(o); }
|
||||
//---Supporting-total-ordering----------
|
||||
auto operator<=>(Digxel const& o) const { return value_ <=> NUM(o); }
|
||||
bool operator== (Digxel const& o) const { return value_ == NUM(o); }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@
|
|||
#include "lib/time/timecode.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
|
||||
//#include <boost/operators.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
#include <compare>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -139,8 +140,6 @@ namespace time {
|
|||
* @see TimeVar when full arithmetics are required
|
||||
*/
|
||||
class TimeValue
|
||||
: boost::totally_ordered<TimeValue,
|
||||
boost::totally_ordered<TimeValue, raw_time_64>>
|
||||
{
|
||||
protected:
|
||||
/** the raw (internal) time value
|
||||
|
|
@ -196,12 +195,12 @@ namespace time {
|
|||
/** @return is in-domain, not a boundary value */
|
||||
bool isRegular() const;
|
||||
|
||||
// Supporting totally_ordered
|
||||
friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
|
||||
friend bool operator< (TimeValue const& t1, raw_time_64 t2) { return t1.t_ < t2 ; }
|
||||
friend bool operator> (TimeValue const& t1, raw_time_64 t2) { return t1.t_ > t2 ; }
|
||||
friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
|
||||
friend bool operator== (TimeValue const& t1, raw_time_64 t2) { return t1.t_ == t2 ; }
|
||||
// Supporting strong total ordering
|
||||
std::strong_ordering operator<=> (TimeValue const&) const =default;
|
||||
bool operator== (TimeValue const&) const =default;
|
||||
|
||||
std::strong_ordering operator<=> (raw_time_64 tt) const { return t_ <=> tt; }
|
||||
bool operator== (raw_time_64 tt) const { return t_ == tt; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -582,7 +581,6 @@ namespace time {
|
|||
*/
|
||||
class TimeSpan
|
||||
: public Time
|
||||
, boost::totally_ordered<TimeSpan>
|
||||
{
|
||||
Duration dur_;
|
||||
|
||||
|
|
@ -651,10 +649,15 @@ namespace time {
|
|||
/** @internal diagnostics */
|
||||
explicit operator std::string() const;
|
||||
|
||||
/// Supporting extended total order, based on start and interval length
|
||||
friend bool operator== (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_==t2.t_ && t1.dur_==t2.dur_; }
|
||||
friend bool operator< (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_< t2.t_ ||
|
||||
(t1.t_==t2.t_ && t1.dur_< t2.dur_);}
|
||||
/// Supporting extended strong total ordering, based on start and interval length
|
||||
std::strong_ordering
|
||||
operator<=> (TimeSpan const& ts) const
|
||||
{
|
||||
auto ord{ t_ <=> ts.t_ };
|
||||
return ord != 0? ord
|
||||
: dur_ <=> ts.dur_;
|
||||
}
|
||||
bool operator== (TimeSpan const& ts) const =default;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,8 @@
|
|||
#include "lib/hash-value.h"
|
||||
#include "lib/p.hpp"
|
||||
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <compare>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
|
@ -137,8 +135,7 @@ namespace asset {
|
|||
* @author Ichthyo
|
||||
*/
|
||||
class Asset
|
||||
: public boost::totally_ordered1< Asset
|
||||
, util::NonCopyable >
|
||||
: util::NonCopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
@ -147,7 +144,6 @@ namespace asset {
|
|||
* sufficiently identifying any given Asset.
|
||||
*/
|
||||
struct Ident
|
||||
: boost::totally_ordered<Ident>
|
||||
{
|
||||
/** element ID, comprehensible but sanitised.
|
||||
* The tuple (category, name, org) is unique.
|
||||
|
|
@ -181,11 +177,13 @@ namespace asset {
|
|||
,const uint ver=1);
|
||||
|
||||
|
||||
int compare (Ident const& other) const;
|
||||
/** ordering of Assets is based on the ordering of Ident tuples,
|
||||
* descending from Category to origin and finally to the asset element ID.
|
||||
* @note version info is ignored for this comparison */
|
||||
auto operator<=>(Ident const& oi) const { return std::tie ( category, org, name)
|
||||
<=> std::tie (oi.category,oi.org,oi.name); }
|
||||
bool operator== (Ident const& oi) const { return 0 == *this <=> oi; }
|
||||
|
||||
/** @note equality ignores version differences */
|
||||
bool operator== (Ident const& oi) const { return compare (oi) ==0; }
|
||||
bool operator< (Ident const& oi) const { return compare (oi) < 0; }
|
||||
|
||||
operator string () const;
|
||||
|
||||
|
|
@ -202,7 +200,7 @@ namespace asset {
|
|||
|
||||
|
||||
bool operator== (Asset const& oa) const { return ident == oa.ident; }
|
||||
bool operator< (Asset const& oa) const { return ident < oa.ident; }
|
||||
auto operator<=>(Asset const& oa) const { return ident <=> oa.ident; }
|
||||
|
||||
virtual operator string () const;
|
||||
|
||||
|
|
@ -300,24 +298,6 @@ namespace asset {
|
|||
|
||||
|
||||
|
||||
/* ====== ordering of Assets and Asset-Pointers ====== */
|
||||
|
||||
/** ordering of Assets is based on the ordering
|
||||
* of Ident tuples, which are supposed to be unique.
|
||||
* By using our customised lumiera::P as smart ptr,
|
||||
* comparison on P<Asset> ptrs will be automatically
|
||||
* forwarded to the Asset comparison operators.
|
||||
* @note version info is irrelevant */
|
||||
inline int
|
||||
Asset::Ident::compare (Asset::Ident const& oi) const
|
||||
{
|
||||
int res;
|
||||
if (0 != (res=category.compare (oi.category))) return res;
|
||||
if (0 != (res=org.compare (oi.org))) return res;
|
||||
return name.compare (oi.name);
|
||||
}
|
||||
|
||||
|
||||
/** promote subtype-ptr to PAsset, e.g. for comparing */
|
||||
template<class A>
|
||||
inline const PcAsset
|
||||
|
|
@ -329,11 +309,11 @@ namespace asset {
|
|||
|
||||
/** type trait for detecting a shared-ptr-to-asset */
|
||||
template <class X>
|
||||
struct is_pAsset : boost::false_type {};
|
||||
struct is_pAsset : std::false_type { };
|
||||
|
||||
template <class A>
|
||||
struct is_pAsset<shared_ptr<A>>
|
||||
: boost::is_base_of<Asset, A> {};
|
||||
: std::is_base_of<Asset, A> { };
|
||||
|
||||
|
||||
/** marker constant denoting a NIL asset */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "lib/hash-standard.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <compare>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
|
||||
|
|
@ -73,29 +74,15 @@ namespace asset {
|
|||
Category (const Kind root, Literal subfolder ="")
|
||||
: kind_(root), path_(subfolder) {};
|
||||
|
||||
bool operator== (Category const& other) const { return kind_== other.kind_ and path_== other.path_; }
|
||||
bool operator!= (Category const& other) const { return kind_!= other.kind_ or path_!= other.path_; }
|
||||
auto operator<=> (Category const&) const =default;
|
||||
|
||||
bool hasKind (Kind refKind) const { return kind_ == refKind; }
|
||||
bool isWithin (Category const&) const;
|
||||
void setPath (string const& newpath) { this->path_ = newpath; }
|
||||
|
||||
|
||||
operator string () const;
|
||||
|
||||
friend size_t hash_value (Category const&);
|
||||
|
||||
|
||||
int
|
||||
compare (Category const& co) const
|
||||
{
|
||||
int res = int(kind_) - int(co.kind_);
|
||||
if (0 != res)
|
||||
return res;
|
||||
else
|
||||
return path_.compare (co.path_);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
//#include "lib/util.hpp"
|
||||
#include "lib/symbol.hpp"
|
||||
|
||||
//#include <boost/operators.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace lumiera{ ///////TODO: shouldn't that be namespace lib? or steam?
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include "lib/format-obj.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -47,7 +46,6 @@ namespace steam {
|
|||
namespace control {
|
||||
namespace err = lumiera::error;
|
||||
|
||||
using boost::equality_comparable;
|
||||
using lib::meta::func::bindLast;
|
||||
using lib::meta::func::chained;
|
||||
using lib::meta::equals_safeInvoke;
|
||||
|
|
@ -77,7 +75,6 @@ namespace control {
|
|||
*/
|
||||
template<typename SIG, typename MEM>
|
||||
class MementoTie
|
||||
: public equality_comparable<MementoTie<SIG,MEM>>
|
||||
{
|
||||
typedef typename CommandSignature<SIG,MEM>::CaptureSig SIG_cap;
|
||||
typedef typename CommandSignature<SIG,MEM>::UndoOp_Sig SIG_undo;
|
||||
|
|
@ -195,7 +192,7 @@ namespace control {
|
|||
template<typename SIG, typename MEM>
|
||||
MementoTie<SIG,MEM>::operator std::string() const
|
||||
{
|
||||
if (!undo_ or !capture_)
|
||||
if (not undo_ or not capture_)
|
||||
return "·noUNDO·";
|
||||
|
||||
if (not isCaptured_)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
#include "steam/asset/pipe.hpp"
|
||||
#include "common/query.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <compare>
|
||||
#include <map>
|
||||
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ namespace mobject {
|
|||
class OutputMapping
|
||||
: public DEF
|
||||
{
|
||||
typedef _def<DEF> Setup;
|
||||
using Setup = _def<DEF>;
|
||||
|
||||
using PId = asset::ID<asset::Pipe>;
|
||||
using PPipe = asset::PPipe;
|
||||
|
|
@ -148,10 +148,11 @@ namespace mobject {
|
|||
* of the specific resolution functor, embedded in the definition context `DEF`,
|
||||
* which was given when instantiating the OutputMapping template.
|
||||
* @note depends on the template parameter of the enclosing OutputMapping type!
|
||||
* @remarks
|
||||
* - final mapping result can be compared to Target
|
||||
* - Resolvers (mapping values) can be compared based on the Pipe-hash
|
||||
*/
|
||||
class Resolver
|
||||
: public boost::equality_comparable<Resolver, Target // final mapping result can be compared to Target...
|
||||
, boost::equality_comparable<Resolver>> // mapping values can be compared.
|
||||
{
|
||||
OutputMapping& thisMapping_;
|
||||
HashVal& pID_;
|
||||
|
|
|
|||
|
|
@ -100,25 +100,25 @@ namespace test {
|
|||
Category c5 (STRUCT);
|
||||
Category c6 (META);
|
||||
|
||||
CHECK (0 > c1.compare(c2));
|
||||
CHECK (0 > c2.compare(c3));
|
||||
CHECK (0 > c3.compare(c4));
|
||||
CHECK (0 > c4.compare(c5));
|
||||
CHECK (0 > c5.compare(c6));
|
||||
CHECK (0 > c1 <=> c2 );
|
||||
CHECK (0 > c2 <=> c3 );
|
||||
CHECK (0 > c3 <=> c4 );
|
||||
CHECK (0 > c4 <=> c5 );
|
||||
CHECK (0 > c5 <=> c6 );
|
||||
|
||||
CHECK (0 ==
|
||||
|
|
|
|||
Loading…
Reference in a new issue