#include <msp/core/attributes.h>
#include <msp/core/maputils.h>
+#include <msp/core/noncopyable.h>
#include <msp/core/refptr.h>
#include "collectionsource.h"
#include "loader.h"
template<typename T>
class CollectionItemType;
+template<typename T>
+class LoadableCollectionItemType;
+
+template<typename T, bool = HasLoader<T>::value>
+struct CollectionItemTypeChooser;
+
+template<typename T>
+struct CollectionItemTypeChooser<T, true>
+{ typedef LoadableCollectionItemType<T> Type; };
+
+template<typename T>
+struct CollectionItemTypeChooser<T, false>
+{ typedef CollectionItemType<T> Type; };
+
/**
A collection of objects that can be loaded from a datafile. Each object is
identified by a name, which must be unique across the entire collection.
between the collections, and are only deleted when all collections in the chain
have been destroyed.
*/
-class Collection
+class Collection: private NonCopyable
{
public:
/**
*/
class Loader: public DataFile::Loader
{
- template<typename T> friend class CollectionItemType;
+ template<typename T> friend class LoadableCollectionItemType;
private:
Collection &coll;
SourceList sources;
Collection *fallback;
- Collection(const Collection &);
- Collection &operator=(const Collection &);
public:
Collection();
virtual ~Collection();
return extract<NCT>(get_var(name, get_type<NCT>(name)));
}
+ /** Finds a typed object in the collection. Returns null if the name does
+ not exist. Throws if the name exists but the object is of an incorrect
+ type. */
+ template<typename T>
+ T *find(const std::string &name) const
+ {
+ ItemMap::const_iterator i = items.find(name);
+ return (i!=items.end() ? extract<typename RemoveConst<T>::Type>(i->second) : 0);
+ }
+
+ template<typename T>
+ T *find(const std::string &name)
+ {
+ typedef typename RemoveConst<T>::Type NCT;
+ const Variant *var = find_var(name, get_type<NCT>(name));
+ return (var ? &extract<NCT>(*var) : 0);
+ }
+
private:
const Variant &get_var(const std::string &, const CollectionItemTypeBase *);
+ const Variant *find_var(const std::string &, const CollectionItemTypeBase *);
template<typename T>
T &extract(const Variant &var) const;
/** Adds a type to the collection. The returned descriptor object reference
can be used to define how objects of that type can be loaded. */
template<typename T>
- CollectionItemType<T> &add_type();
+ typename CollectionItemTypeChooser<T>::Type &add_type();
/** Returns a mutable reference to an existing type descriptor. This can be
used to e.g. override the creator function of a type added by a base class. */
template<typename T>
- CollectionItemType<T> &modify_type();
+ typename CollectionItemTypeChooser<T>::Type &modify_type();
private:
/** Returns the descriptor for a type, or null if one isn't defined. An
public:
virtual ~CollectionItemTypeBase();
+protected:
void set_keyword(const std::string &);
- const std::string &get_keyword() const { return kwd; }
void add_suffix(const std::string &);
+public:
+ const std::string &get_keyword() const { return kwd; }
bool match_name(const std::string &) const;
virtual bool is_same_type(const CollectionItemTypeBase &) const = 0;
virtual bool check_item_type(const Variant &) const = 0;
virtual bool check_item_type(const Variant &var) const
{ return var.check_type<RefPtr<T> >(); }
- virtual void add_to_loader(Collection::Loader &loader) const
- { loader.add(kwd, &Collection::Loader::item<T, T>); }
+ virtual void add_to_loader(Collection::Loader &) const
+ { }
virtual bool can_create() const
{ return creat!=0; }
coll.add(name, obj);
}
+ virtual void load_item(Collection &, Parser &, const std::string &) const
+ {
+ throw std::runtime_error("this type cannot be loaded");
+ }
+};
+
+
+template<typename T>
+class LoadableCollectionItemType: public CollectionItemType<T>
+{
+public:
+ virtual void add_to_loader(Collection::Loader &loader) const
+ { loader.add(this->kwd, &Collection::Loader::item<T, T>); }
+
virtual void load_item(Collection &coll, Parser &parser, const std::string &name) const
{
RefPtr<T> obj = new T;
}
template<typename T>
-CollectionItemType<T> &Collection::add_type()
+typename CollectionItemTypeChooser<T>::Type &Collection::add_type()
{
- CollectionItemType<T> *type = new CollectionItemType<T>;
+ typename CollectionItemTypeChooser<T>::Type *type = new typename CollectionItemTypeChooser<T>::Type;
types.push_back(type);
return *type;
}
template<typename T>
-CollectionItemType<T> &Collection::modify_type()
+typename CollectionItemTypeChooser<T>::Type &Collection::modify_type()
{
for(TypeList::const_iterator j=types.begin(); j!=types.end(); ++j)
if(CollectionItemType<T> *t = dynamic_cast<CollectionItemType<T> *>(*j))