WIP reorganize the ordering relation on assets

(should simplify handling of comparisons at various places)
This commit is contained in:
Fischlurch 2008-04-03 03:50:28 +02:00
parent 3d2791b91e
commit 162976a4cf
2 changed files with 68 additions and 53 deletions

View file

@ -39,7 +39,7 @@
** value. For example the asset::Media#getID returns an ID<Media>. 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 <vector>
#include <set>
#include <tr1/memory>
#include <boost/operators.hpp>
#include <boost/utility.hpp>
@ -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<Ident>
{
/** 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<Asset>& getID() const { return id; }
virtual const ID<Asset>& 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<Asset> 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<class A>
inline const PcAsset
@ -304,30 +320,27 @@ namespace asset
/** ordering of Asset smart ptrs based on Ident tuple.
* @todo currently supporting only smart_ptr<Asset>.
* @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<class PA1, class PA2>
inline bool operator== (PA1 const& a1, PA2 const& a2) { return pAsset(a1) == pAsset(a2); }
template<class PA1, class PA2>
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<class PTR>
struct asset_total_ordering : public boost::totally_ordered<PTR>
{ };
template struct asset_total_ordering<PAsset>;
template struct asset_total_ordering<PcAsset>;
/** convienient for debugging */

View file

@ -26,8 +26,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/lambda/lambda.hpp>
//#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/bind.hpp>
#include <iostream>
#include <string>
#include <set>
@ -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<class COLL>
@ -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<uint> 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);
}