Quote:Original post by nlbs
So you meant I need to do something like.
*** Source Snippet Removed ***
Right ??
If I code like this e.g. `this =` syntax says `lvalue required as left operand of assignment`
I meant I cant understand how to call/use the clone() from copy constructor or operator=()
You need to add it to JType. Something like this:
#include <iostream>#include <string>#include <map>struct JType { JType() { std::cout << "JType()" << std::endl; } virtual ~JType() { std::cout << "~JType()" << std::endl; } virtual void commit() = 0; virtual JType * clone() const = 0;};struct JDefault : public JType { JDefault() { std::cout << "JDefault()" << std::endl; } ~JDefault() { std::cout << "~JDefault()" << std::endl; } void commit() { std::cout << "Commit not supported" << std::endl; } JDefault * clone() const { return new JDefault(*this); }};struct JString : public JType { JString(const std::string & value = "Hello World") : s(value) { std::cout << "JString()" << std::endl; } ~JString() { std::cout << "~JString()" << std::endl; } void commit() { std::cout << s << std::endl; } JString * clone() const { return new JString(*this); }private: std::string s;};class Object { typedef JType * T; typedef std::map<std::string, T> List; struct Proxy { friend class Object; template < class U > Proxy & operator=(const U & rhs) { clear(); ref = new U(rhs); return *this; } bool exists() const { return ref != NULL; } void clear() { delete ref; ref = NULL; } T operator->() const { return value(); } T operator*() const { return value(); } private: Proxy(const List::iterator & i) : ref(i->second) {} Proxy(const Proxy & other) : ref(other.ref) {} // assignment isn't allowed Proxy & operator=(const Proxy &) { } T value() const { static JDefault def; return (ref == NULL) ? &def : ref; } T & ref; }; struct ManagedMap { ~ManagedMap() { List::iterator i = list.begin(); for (List::iterator i = list.begin(); i!= list.end(); ++i) delete i->second; } List::iterator insert(const std::string & key) { return list.insert(list.end(), std::make_pair(key, T(NULL))); } List list; }; void swap(ManagedMap & lhs, ManagedMap & rhs) { std::swap(lhs.list, rhs.list); } List & list() { return entries.list; } const List & list() const { return entries.list; } ManagedMap entries;public: Object() {} Object(const Object & other) { ManagedMap temp; for (List::const_iterator i = other.list().begin(); i != other.list().end(); ++i) { List::iterator curr = temp.insert(i->first); if (i->second != NULL) curr->second = i->second->clone(); } swap(entries, temp); } Object & operator=(const Object & other) { Object o(other); swap(entries, o.entries); return *this; } ~Object() {} Proxy operator[](const std::string & key) { List::iterator i = list().find(key); if (i != list().end()) { return Proxy(i); } else { return Proxy(entries.insert(key)); } } bool has(const std::string & key) const { return list().count(key) != 0; }};int main(int argc, char* argv[]){ Object o; JString js; o["a"] = js; o["math"] = JString(); Object q; o = o; q = o; Object r; r = q; r["foo"] = JDefault(); r["bar"] = JString("bar"); o = r; if (o["empty"].exists()) std::cout << "'empty' should not exist" << std::endl; o["math"]->commit(); o["math"].clear(); o["math"]->commit(); o["foo"]->commit(); o["bar"]->commit(); o["empty"]->commit();}
A few comments on that:
- I still don't guarantee I covered all the corner cases
- This is why C++ is hard
- To understand why things are implemented in this way, best references are Exceptional C++, More Exceptional C++ and few others.
I'd strongly suggest you look into those sources and examine the finer points of C++ before trying designs like this. The difference between something that compiles and something that works somewhat reliably is simply too big in C++.