From: Mikko Rasa Date: Sun, 19 Apr 2020 14:09:07 +0000 (+0300) Subject: Allow non-loadable types in collections X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=commitdiff_plain;h=465ac6c7ceda80ce7e2f6e3f7b6901ce0921406e Allow non-loadable types in collections Custom collection classes may wish to provide objects of such types through creator functions. --- diff --git a/source/collection.h b/source/collection.h index 5521975..d0e8a1a 100644 --- a/source/collection.h +++ b/source/collection.h @@ -19,6 +19,20 @@ class CollectionItemTypeBase; template class CollectionItemType; +template +class LoadableCollectionItemType; + +template::value> +struct CollectionItemTypeChooser; + +template +struct CollectionItemTypeChooser +{ typedef LoadableCollectionItemType Type; }; + +template +struct CollectionItemTypeChooser +{ typedef CollectionItemType 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. @@ -44,7 +58,7 @@ public: */ class Loader: public DataFile::Loader { - template friend class CollectionItemType; + template friend class LoadableCollectionItemType; private: Collection &coll; @@ -235,12 +249,12 @@ protected: /** 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 - CollectionItemType &add_type(); + typename CollectionItemTypeChooser::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 - CollectionItemType &modify_type(); + typename CollectionItemTypeChooser::Type &modify_type(); private: /** Returns the descriptor for a type, or null if one isn't defined. An @@ -323,9 +337,11 @@ protected: 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; @@ -448,8 +464,8 @@ public: virtual bool check_item_type(const Variant &var) const { return var.check_type >(); } - virtual void add_to_loader(Collection::Loader &loader) const - { loader.add(kwd, &Collection::Loader::item); } + virtual void add_to_loader(Collection::Loader &) const + { } virtual bool can_create() const { return creat!=0; } @@ -463,6 +479,20 @@ public: coll.add(name, obj); } + virtual void load_item(Collection &, Parser &, const std::string &) const + { + throw std::runtime_error("this type cannot be loaded"); + } +}; + + +template +class LoadableCollectionItemType: public CollectionItemType +{ +public: + virtual void add_to_loader(Collection::Loader &loader) const + { loader.add(this->kwd, &Collection::Loader::item); } + virtual void load_item(Collection &coll, Parser &parser, const std::string &name) const { RefPtr obj = new T; @@ -486,15 +516,15 @@ T &Collection::extract(const Variant &var) const } template -CollectionItemType &Collection::add_type() +typename CollectionItemTypeChooser::Type &Collection::add_type() { - CollectionItemType *type = new CollectionItemType; + typename CollectionItemTypeChooser::Type *type = new typename CollectionItemTypeChooser::Type; types.push_back(type); return *type; } template -CollectionItemType &Collection::modify_type() +typename CollectionItemTypeChooser::Type &Collection::modify_type() { for(TypeList::const_iterator j=types.begin(); j!=types.end(); ++j) if(CollectionItemType *t = dynamic_cast *>(*j)) diff --git a/source/meta.h b/source/meta.h index ac6ec1b..51bc924 100644 --- a/source/meta.h +++ b/source/meta.h @@ -18,6 +18,18 @@ struct CheckCollectionType: Sfinae template struct NeedsCollection: Sfinae::Evaluate { }; +/** +Helper struct to determine whether a type has a Loader class. +*/ +struct CheckLoader: Sfinae +{ + template + static Yes f(typename T::Loader *); + using Sfinae::f; +}; + +template struct HasLoader: Sfinae::Evaluate { }; + } // namespace DataFile } // namespace Msp