<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-850900244885539293</id><updated>2011-09-28T00:10:09.067-07:00</updated><title type='text'>Sudeep's Weblog</title><subtitle type='html'>Welcome to my WebLog.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sjweblogs.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/850900244885539293/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sjweblogs.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sudeep Jathar</name><uri>http://www.blogger.com/profile/18396879283887513297</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-850900244885539293.post-3864629607364498927</id><published>2008-08-08T14:37:00.000-07:00</published><updated>2008-08-09T10:13:13.348-07:00</updated><title type='text'>C++ &gt; Storing heterogenous objects in a container</title><content type='html'>While designing in C++, many times I got stuck to get a container which can store objects of multiple types. Fortunately for me I always managed to find an alternative design in which there was no such need. Recently, I got stuck and I *had* to find a way to do this. This was the situation:&lt;br /&gt;&lt;br /&gt;There is an interface( or class with all pure virtual functions) ITask. I wanted to create many task classes which adhere to this interface. The project demanded that the task objects to be created and used (and executed) in a uniform manner. Since every task might take different type and number of arguments, I had to find a way to create an container which can store objects of different types. The problem is that STL containers like vector&lt;t&gt; can store objects of only one type or of derived classes of the type for which the vector was created.&lt;br /&gt;&lt;br /&gt;In terms of code I wanted something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Lets say I have a task which creates report &lt;br /&gt;// by accessing tables.&lt;br /&gt;// So the inputs to the task are:&lt;br /&gt;// 1. Database connection&lt;br /&gt;// 2. Output file name&lt;br /&gt;&lt;br /&gt;class CreateReport : public ITask&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; // I did not want seperate class like ArgumentList for&lt;br /&gt; // each Task class. The same class should be used to pass&lt;br /&gt; // the arguments for all task classes. This is what I mean&lt;br /&gt; // by "uniform manner" mentioned earlier.&lt;br /&gt; void run(const ArgumentList* args) // Inherited from ITask&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt;  DBConnection* conn = args-&gt;getValue("connection");&lt;br /&gt;  string fileName = args-&gt;getValue("filename");&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt; ...&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Using CreateReport&lt;br /&gt;...&lt;br /&gt;ArgumentList* a =  new ArgumentList();&lt;br /&gt;a.add(new DBConnection(connectionString));&lt;br /&gt;a.add("report.txt");&lt;br /&gt;ITask* t = new CreateReport();&lt;br /&gt;t-&gt;run(a);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When I came up with a solution, it was very obvious and I thought "Why could'nt I think this before?"&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution &gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, if you know Boost, you must be thinking "Well, there are tuples which can be used to store multiple types of objects". The issue is that in my case I don't know at compile time how many arguments are going to be passed, so using tuple is not an option. I will discuss pros and cons of my solution &amp; tuples later below. First the solution:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Interface&lt;br /&gt;class IArgument&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;      virtual string getName() = 0;&lt;br /&gt;      virtual ~IArgument(){}&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;template&lt;class VALUE_TYPE&gt;&lt;br /&gt;class Argument : public IArgument&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    Argument(string i_name, VALUE_TYPE i_value)&lt;br /&gt;      :m_name(i_name), m_value(i_value)&lt;br /&gt;      {&lt;br /&gt;      }&lt;br /&gt;      &lt;br /&gt;      /// Get the argument name&lt;br /&gt;      virtual string getName() { return m_name; }&lt;br /&gt;      &lt;br /&gt;      VALUE_TYPE getValue() { return m_value; }&lt;br /&gt;      &lt;br /&gt;   protected:&lt;br /&gt;      string m_name;&lt;br /&gt;      VALUE_TYPE m_value;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class NamedArguments&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;   &lt;br /&gt;  /// Gets the value by name&lt;br /&gt;  template&lt;class VALUE_TYPE&gt;&lt;br /&gt;  VALUE_TYPE getValue(string i_argName)&lt;br /&gt;  {&lt;br /&gt;     map&lt;string, IArgument*&gt;::iterator itr;&lt;br /&gt;         &lt;br /&gt;     if( (itr = m_argMap.find(i_argName)) == m_argMap.end() )&lt;br /&gt;        THROW_AMR_EXCEPTION_2(ArgumentNotFound, i_argName);&lt;br /&gt;      Argument&lt;VALUE_TYPE&gt;* arg = NULL;&lt;br /&gt;     if( (arg = dynamic_cast&lt; Argument&lt;VALUE_TYPE&gt;* &gt;(itr-&gt;second))  == NULL)&lt;br /&gt;         THROW_EXCEPTION(InvalidArgumentType);&lt;br /&gt;                             &lt;br /&gt;      return (VALUE_TYPE)arg-&gt;getValue();      &lt;br /&gt;  }&lt;br /&gt;      &lt;br /&gt;  /// Adds the argument and value&lt;br /&gt;  template&lt;class VALUE_TYPE&gt;&lt;br /&gt;  void add(string i_argName, VALUE_TYPE i_value)&lt;br /&gt;  {&lt;br /&gt;     map&lt;string, IArgument*&gt;::iterator itr;&lt;br /&gt;         &lt;br /&gt;     // Ignore if the argument is already present&lt;br /&gt;     if( (itr = m_argMap.find(i_argName)) != m_argMap.end() )&lt;br /&gt;        return;&lt;br /&gt;               &lt;br /&gt;     m_argMap.insert&lt;br /&gt;     ( &lt;br /&gt;        map&lt;string, IArgument*&gt;::value_type&lt;br /&gt;        (&lt;br /&gt;           i_argName, new Argument&lt;VALUE_TYPE&gt;(i_argName, i_value) &lt;br /&gt;        ) &lt;br /&gt;     );&lt;br /&gt;         &lt;br /&gt;     //m_argMap[i_argName] = new Argument&lt;VALUE_TYPE&gt;(i_argName, i_value);&lt;br /&gt;  }&lt;br /&gt;      &lt;br /&gt;  /// DTor&lt;br /&gt;      &lt;br /&gt;  ~NamedArguments()&lt;br /&gt;  {         &lt;br /&gt;     for(map&lt;string, IArgument*&gt;::iterator itr = m_argMap.begin(); &lt;br /&gt;     itr != m_argMap.end(); itr++ )&lt;br /&gt;            delete itr-&gt;second;&lt;br /&gt;  }&lt;br /&gt;      &lt;br /&gt;private:&lt;br /&gt;   &lt;br /&gt;  map&lt;string, IArgument*&gt; m_argMap;&lt;br /&gt;   //map&lt;string, int&gt; m_argNames;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// &lt;br /&gt;// And ... this is how its used??&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;NamedArguments n;&lt;br /&gt;n.add&amp;lt;DBConnection*&amp;gt;("connection", conn);&lt;br /&gt;n.add&amp;lt;string&amp;gt;("filename",string("report.txt"));&lt;br /&gt;&lt;br /&gt;CreateReport r;&lt;br /&gt;r.run(&amp;n);&lt;br /&gt;&lt;br /&gt;// ... The CreateReport::run() will look like &lt;br /&gt;void CreateReport::run(const NamedArguments* args)&lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   DBConnection* conn = args-&gt;getValue&amp;lt;DBConnection*&amp;gt;("connection");&lt;br /&gt;   string filename = args-&gt;getValue&amp;lt;string&amp;gt;("filename");&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pros and cons of this solution and tuple to follow...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/t&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/850900244885539293-3864629607364498927?l=sjweblogs.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sjweblogs.blogspot.com/feeds/3864629607364498927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=850900244885539293&amp;postID=3864629607364498927' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/850900244885539293/posts/default/3864629607364498927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/850900244885539293/posts/default/3864629607364498927'/><link rel='alternate' type='text/html' href='http://sjweblogs.blogspot.com/2008/08/c-storing-heterogenous-objects-in.html' title='C++ &gt; Storing heterogenous objects in a container'/><author><name>Sudeep Jathar</name><uri>http://www.blogger.com/profile/18396879283887513297</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
