From: Mikko Rasa Date: Tue, 16 Oct 2007 19:48:31 +0000 (+0000) Subject: Support const types with Collection properly X-Git-Tag: 1.0~15 X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=commitdiff_plain;h=92644bf892df1220c8df67e1fc3da85dd02c53c5 Support const types with Collection properly Delete old action in Loader if a new one replaces it Add a namespace-scope load function taking an extra argument --- diff --git a/source/collection.h b/source/collection.h index 3a3b90e..85ca843 100644 --- a/source/collection.h +++ b/source/collection.h @@ -31,6 +31,14 @@ struct NeedsCollection enum { result=(sizeof(f(0))==sizeof(Yes)) }; }; +template +struct RemoveConst +{ typedef T Type; }; + +template +struct RemoveConst +{ typedef 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. @@ -167,7 +175,10 @@ private: ItemKeywordSeq keywords; ItemCreatorSeq creators; + Collection(const Collection &); + Collection &operator=(const Collection &); public: + Collection() { } virtual ~Collection(); /** @@ -180,7 +191,7 @@ public: if(items.count(name)) throw KeyError("Duplicate key '"+name+"' in collection"); - items[name]=new Item(d); + items[name]=new Item::Type>(d); } /** @@ -189,11 +200,13 @@ public: template T &get(const std::string &name) const { + typedef typename RemoveConst::Type NCT; + ItemMap::const_iterator i=items.find(name); if(i==items.end()) throw KeyError("Item '"+name+"' not found in collection"); - const Item *item=dynamic_cast *>(i->second); + const Item *item=dynamic_cast *>(i->second); if(!item) throw TypeError("Item '"+name+"' is not of correct type"); @@ -208,20 +221,22 @@ public: template T &get(const std::string &name) { + typedef typename RemoveConst::Type NCT; + ItemMap::const_iterator i=items.find(name); if(i==items.end()) { for(ItemCreatorSeq::iterator j=creators.begin(); j!=creators.end(); ++j) - if(T *d=(*j)->create(*this, name)) + if(NCT *d=(*j)->create(*this, name)) { // We already know that the item didn't exist yet - items[name]=new Item(d); + items[name]=new Item(d); return *d; } throw KeyError("Item '"+name+"' not found in collection"); } - const Item *item=dynamic_cast *>(i->second); + const Item *item=dynamic_cast *>(i->second); if(!item) throw TypeError("Item '"+name+"' is not of correct type"); diff --git a/source/loader.cpp b/source/loader.cpp index cf1a5ac..0a9f68f 100644 --- a/source/loader.cpp +++ b/source/loader.cpp @@ -34,6 +34,18 @@ Loader::~Loader() delete i->second; } +void Loader::add(const string &k, LoaderAction *a) +{ + ActionMap::iterator i=actions.find(k); + if(i!=actions.end()) + { + delete i->second; + i->second=a; + } + else + actions[k]=a; +} + void Loader::load_statement(const Statement &st) { cur_st=&st; diff --git a/source/loader.h b/source/loader.h index da1da3a..8d26a41 100644 --- a/source/loader.h +++ b/source/loader.h @@ -239,40 +239,40 @@ protected: */ template void add(const std::string &k, void (L::*func)()) - { actions.insert(typename ActionMap::value_type(k, new LoaderFunc0(func))); } + { add(k, new LoaderFunc0(func)); } template void add(const std::string &k, void (L::*func)(A0)) - { actions.insert(typename ActionMap::value_type(k, new LoaderFunc1(func))); } + { add(k, new LoaderFunc1(func)); } template void add(const std::string &k, void (L::*func)(A0, A1)) - { actions.insert(typename ActionMap::value_type(k, new LoaderFunc2(func))); } + { add(k, new LoaderFunc2(func)); } template void add(const std::string &k, void (L::*func)(A0, A1, A2)) - { actions.insert(typename ActionMap::value_type(k, new LoaderFunc3(func))); } + { add(k, new LoaderFunc3(func)); } template void add(const std::string &k, void (L::*func)(A0, A1, A2, A3)) - { actions.insert(typename ActionMap::value_type(k, new LoaderFunc4(func))); } + { add(k, new LoaderFunc4(func)); } /** Adds a keyword that is loaded into a variable of the loaded object. */ template void add(const std::string &k, T0 L::*p0) - { actions.insert(typename ActionMap::value_type(k, new LoadValue1(p0))); } + { add(k, new LoadValue1(p0)); } template void add(const std::string &k, T0 L::*p0, T1 L::*p1) - { actions.insert(typename ActionMap::value_type(k, new LoadValue2(p0, p1))); } + { add(k, new LoadValue2(p0, p1)); } /** Adds a keyword that is recognized but ignored. */ void add(const std::string &k) - { actions.insert(ActionMap::value_type(k, 0)); } + { add(k, 0); } /** Loads a sub-object from the statement being processed. The Loader class of @@ -328,6 +328,7 @@ private: ActionMap actions; const Statement *cur_st; + void add(const std::string &, LoaderAction *); void load_statement(const Statement &st); }; @@ -346,6 +347,18 @@ void load(T &obj, const std::string &fn) loader.load(parser); } +template +void load(T &obj, const std::string &fn, U arg) +{ + std::ifstream in(fn.c_str()); + if(!in) + throw Exception("Couldn't open "+fn); + + Parser parser(in, fn); + typename T::Loader loader(obj, arg); + loader.load(parser); +} + } // namespace DataFile } // namespace Msp