diff --git a/src/proc/asset.hpp b/src/proc/asset.hpp index bc587cc96..b9a85e5ae 100644 --- a/src/proc/asset.hpp +++ b/src/proc/asset.hpp @@ -39,7 +39,7 @@ ** value. For example the asset::Media#getID returns an ID. By using the ** templated query function AssetManager#getAsset, we can get at references to the more ** specific subinterface asset::media just by using the ID value in a typesafe manner. - ** This helps avoiding dynamic typing and switch-on-type, leading to much more robust, + ** This helps avoiding dynamic typing and switch-on-type, leading to more robust, ** extensible and clear code. ** ** (Implementation detail: as g++ is not able to handle member function template @@ -65,6 +65,7 @@ #include #include #include +#include #include @@ -128,12 +129,14 @@ namespace asset * asset::Effect, asset::Codec, asset::Track, asset::Dataset. * @note Assets objects have a strict unique identity and because of this are non-copyable. * You can not create an Asset derived object without registering it with the AssetManager - * automatically. I is possible to copy the PAsset (smart pointer) though. + * automatically. It is possible to copy the PAsset (smart pointer) though. * * @since 09/2007 * @author Ichthyo */ - class Asset : private boost::noncopyable + class Asset + : boost::totally_ordered< Asset, + boost::noncopyable> { public: @@ -142,6 +145,7 @@ namespace asset * sufficiently identifying any given Asset. */ struct Ident + : boost::totally_ordered { /** element ID, comprehensible but sanitized. * The tuple (category, name, org) is unique. @@ -174,20 +178,13 @@ namespace asset const string& o = "lumi", const uint ver=1); + + int compare (const Ident& other) const; + /** @note equality ignores version differences */ - bool operator== (const Ident& other) const - { - return org == other.org - && name == other.name - && category == other.category; - } - bool operator!= (const Ident& other) const - { - return !operator==(other); - } - - int compare (const Ident& other) const; - + bool operator== (const Ident& oi) const { return compare (oi) ==0; } + bool operator< (const Ident& oi) const { return compare (oi) < 0; } + operator string () const; }; @@ -197,11 +194,16 @@ namespace asset public: const Ident ident; ///< Asset identification tuple - virtual const ID& getID() const { return id; } - + virtual const ID& getID() const { return id; } + + + bool operator== (const Asset& oa) const { return ident == oa.ident; } + bool operator< (const Asset& oa) const { return ident < oa.ident; } + virtual operator string () const; + protected: const ID id; ///< Asset primary key. @@ -293,6 +295,20 @@ 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. + * @note version info is irrelevant */ + inline int + Asset::Ident::compare (const Asset::Ident& 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 inline const PcAsset @@ -304,30 +320,27 @@ namespace asset /** ordering of Asset smart ptrs based on Ident tuple. * @todo currently supporting only smart_ptr. * @todo should better be done using boost::operator */ - inline bool operator== (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && ( 0==a1->ident.compare(a2->ident));} - inline bool operator< (const PcAsset& a1, const PcAsset& a2) { return a1 && a2 && (-1==a1->ident.compare(a2->ident));} - inline bool operator> (const PcAsset& a1, const PcAsset& a2) { return a2 < a1; } - inline bool operator>= (const PcAsset& a1, const PcAsset& a2) { return !(a1 < a2); } - inline bool operator<= (const PcAsset& a1, const PcAsset& a2) { return !(a1 > a2); } - inline bool operator!= (const PcAsset& a1, const PcAsset& a2) { return !(a1== a2); } + inline bool operator== (PcAsset const& a1, PcAsset const& a2) { return a1 && a2 && ( (*a1) == (*a2));} + inline bool operator< (PcAsset const& a1, PcAsset const& a2) { return a1 && a2 && ( (*a1) < (*a2));} - inline bool operator== (const PAsset& a1, const PAsset& a2) { return pAsset(a1) == pAsset(a2); } - inline bool operator< (const PAsset& a1, const PAsset& a2) { return pAsset(a1) < pAsset(a2); } - inline bool operator> (const PAsset& a1, const PAsset& a2) { return pAsset(a1) > pAsset(a2); } - inline bool operator>= (const PAsset& a1, const PAsset& a2) { return pAsset(a1) >= pAsset(a2); } - inline bool operator<= (const PAsset& a1, const PAsset& a2) { return pAsset(a1) <= pAsset(a2); } - inline bool operator!= (const PAsset& a1, const PAsset& a2) { return pAsset(a1) != pAsset(a2); } - - /** ordering of Asset Ident tuples. - * @note version is irrelevant */ - inline int - Asset::Ident::compare (const Asset::Ident& 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); - } + template + inline bool operator== (PA1 const& a1, PA2 const& a2) { return pAsset(a1) == pAsset(a2); } + + template + inline bool operator< (PA1 const& a1, PA2 const& a2) { return pAsset(a1) < pAsset(a2); } + + + /** build ordering of Asset shared pointers on the ordering of the pointed to assets. + * Because we can't define member operators for shared-ptrs, we explicitly instantiate + * the boost ordering concept template for all Asset kinds we want to use... + */ + template + struct asset_total_ordering : public boost::totally_ordered + { }; + + template struct asset_total_ordering; + template struct asset_total_ordering; + /** convienient for debugging */ diff --git a/tests/components/common/removefromsettest.cpp b/tests/components/common/removefromsettest.cpp index bf1629378..c51d02019 100644 --- a/tests/components/common/removefromsettest.cpp +++ b/tests/components/common/removefromsettest.cpp @@ -26,8 +26,7 @@ #include #include -//#include -#include +#include #include #include #include @@ -43,9 +42,9 @@ namespace util { using util::for_each; using boost::lambda::_1; -// using boost::function; + using boost::lambda::bind; using boost::lexical_cast; - using boost::bind; + template @@ -57,7 +56,6 @@ namespace util cout << "]\n"; } - bool killerselector (string description, uint candidate) { @@ -68,31 +66,35 @@ namespace util class RemoveFromSet_test : public Test { - virtual void run (Arg arg) + virtual void + run (Arg arg) { test_remove (" nothing "); test_remove ("0"); test_remove ("9"); test_remove ("5"); - test_remove ("0 2 4 6 8"); - test_remove ("1 3 5 7 9"); + test_remove ("0 2 4 6 8 "); + test_remove (" 1 3 5 7 9"); test_remove ("0 1 2 3 4 5 6 7 8 9"); test_remove ("0 1 2 3 4 5 6 7 8 "); test_remove (" 1 2 3 4 5 6 7 8 9"); test_remove ("0 1 2 3 4 6 7 8 9"); } - /** @test populate a test set, remove the denoted elements - * and print the result - */ + + /** @test populate a test set, + * remove the denoted elements + * and print the result... */ + void test_remove (string elems_to_remove) { std::set theSet; for (int i=0; i<10; ++i) - theSet.push_back (i); + theSet.insert (i); util::remove_if (theSet, bind( killerselector, elems_to_remove, _1)); + cout << "removed " << elems_to_remove << " ---> "; show (theSet); }