Lots of Macros, can someone explain what these do?

Started by
14 comments, last by Arild Fines 18 years, 4 months ago
Quote:Original post by Shamino
Question though, why does he need 16 factories?


He likes the smoke. [grin]
- blew
Advertisement
So, since the template class has 16 arguements, normally he'd have to write 16 template classes to pass every single thing he needs to the one template class...

So he made a macro, nifty...

And I wouldn't call it a hack, I'd call it a nice solution.

Is this honestly an efficient way to create new instances of objects during runtime?
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
Quote:Original post by ToohrVyk
This is truly ugly, by the way.


Yea, but it let's you do something really beautiful though...
Yeah, it sure does, talk about, the holy grail of oop...
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
And here it is, directly from the man himself, Robert Geiman.

Quote:
Attached is a text file that basically shows the output. Basically, the macro is creating 16 different versions of the same class, with each version containing an extra template parameter. These parameters are for constructor parameters you may want to pass when creating instances of your class.

My text file only includes the first 3 versions, all seperated by a ////////////// line, so you can easily compare the different versions of the class. Even though I've only included the first 3 class outputs, you can look at the differences between them and easily create the other 12 versions.

The reason for the macro's was so that you don't HAVE to create all 15 versions... and then make changes to ALL 15 if you find a bug in the class, etc.

Hope this helps!

Rob Geiman


template<typename BaseClassType, typename ClassType> BaseClassType CreateObject(){   return new ClassType;}template<typename BaseClassType, typename UniqueIdType> class ObjectFactory<BaseClassType(), UniqueIdType> { private:    typedef BaseClassType(*CreateObjectFunc)();public:   typedef typename std::map<UniqueIdType, CreateObjectFunc>::const_iterator ConstIterator;   typedef typename std::map<UniqueIdType, CreateObjectFunc>::iterator Iterator;      template<typename ClassType>   bool Register(UniqueIdType unique_id)   {      if (m_object_creator.find(unique_id) != m_object_creator.end())         return false; m_object_creator[unique_id] = &CreateObject<BaseClassType , ClassType>;            return true;   }      bool Unregister(UniqueIdType unique_id)   {      return (m_object_creator.erase(unique_id) == 1);   }   BaseClassType Create(UniqueIdType unique_id )   {      Iterator iter = m_object_creator.find(unique_id);            if (iter == m_object_creator.end())         return 0;            return ((*iter).second)();   }      ConstIterator GetBegin() const   {      return m_object_creator.begin();   }      Iterator GetBegin()   {      return m_object_creator.begin();   }      ConstIterator GetEnd() const   {      return m_object_creator.end();   }     Iterator GetEnd()   {      return m_object_creator.end();   }protected:   std::map<UniqueIdType, CreateObjectFunc> m_object_creator;};///////////////////////////////////////////////////////////////////////////////template<typename BaseClassType, typename A0, typename ClassType> BaseClassType CreateObject(A0 a0){   return new ClassType(a0);}template<typename BaseClassType, typename A0, typename UniqueIdType>class ObjectFactory<BaseClassType(A0), UniqueIdType>{private:   typedef BaseClassType(*CreateObjectFunc)(A0 a0);public:   typedef typename std::map<UniqueIdType, CreateObjectFunc>::const_iterator ConstIterator;   typedef typename std::map<UniqueIdType, CreateObjectFunc>::iterator Iterator;      template<typename ClassType>   bool Register(UniqueIdType unique_id)   {      if (m_object_creator.find(unique_id) != m_object_creator.end())         return false;            m_object_creator[unique_id] = &CreateObject<BaseClassType, A0, ClassType>;            return true;   }      bool Unregister(UniqueIdType unique_id)    {      return (m_object_creator.erase(unique_id) == 1);   }      BaseClassType Create(UniqueIdType unique_id, A0 a0)   {      Iterator iter = m_object_creator.find(unique_id);      if (iter == m_object_creator.end())         return 0;            return ((*iter).second)(a0);   }      ConstIterator GetBegin() const   {      return m_object_creator.begin();   }      Iterator GetBegin()   {      return m_object_creator.begin();   }      ConstIterator GetEnd() const   {      return m_object_creator.end();   }      Iterator GetEnd()   {      return m_object_creator.end();   }protected:   std::map<UniqueIdType, CreateObjectFunc> m_object_creator;};///////////////////////////////////////////////////////////////////////////////template<typename BaseClassType, typename A0, typename A1, typename ClassType> BaseClassType CreateObject(A0 a0, A1 a1){   return new ClassType(a0, a1);}template<typename BaseClassType, typename A0, typename A1, typename UniqueIdType>class ObjectFactory<BaseClassType(A0, A1), UniqueIdType>{private:   typedef BaseClassType(*CreateObjectFunc)(A0 a0, A1 a1);public:   typedef typename std::map<UniqueIdType, CreateObjectFunc>::const_iterator ConstIterator;   typedef typename std::map<UniqueIdType, CreateObjectFunc>::iterator Iterator;      template<typename ClassType>    bool Register(UniqueIdType unique_id)   {      if (m_object_creator.find(unique_id) != m_object_creator.end())         return false;            m_object_creator[unique_id] = &CreateObject<BaseClassType, A0, A1, ClassType>;            return true;   }      bool Unregister(UniqueIdType unique_id)   {      return (m_object_creator.erase(unique_id) == 1);   }      BaseClassType Create(UniqueIdType unique_id, A0 a0, A1 a1)   {      Iterator iter = m_object_creator.find(unique_id);            if (iter == m_object_creator.end())         return 0;            return ((*iter).second)(a0, a1);   }      ConstIterator GetBegin() const   {      return m_object_creator.begin();   }   Iterator GetBegin()   {      return m_object_creator.begin();   }      ConstIterator GetEnd() const   {      return m_object_creator.end();   }      Iterator GetEnd()   {      return m_object_creator.end();   }protected:   std::map<UniqueIdType, CreateObjectFunc> m_object_creator;};...



Also, should I rebuild my engine to fit VC++7.1 standards?

Quote:
Important Note: This code has been tested on Visual C++ 7.1. However, because the final implementation of the object factory uses partial template specialization some non-compliant compilers, such as Visual C++ 6.0, will not be able to compile this code.

Because of this, the source attached to this article also contains a special version of the object factory written specifically for Visual C++ 6.0. To get around the lack of partial template specialization support on Visual C++ 6.0 we must have a separate object factory class for each constructor parameter. Also, because of Visual C++ 6.0's lack of 'explicit template argument specification for member functions' support we must use a hack on the Register function. Below is an example of how to use the object factory in Visual C++ 6.0:



Also, I sent him a reply and asked

Shamino
Quote:
Holy wow, nice macro....

Basically with this lil snippet

MACRO_REPEAT(16, OBJECT_FACTORY)

So, for that final super template (the one in your final code) it requires a whole 15 parameters (which would also require template classes to make)? Or are you just only using a few of these 15?

Are you like, creating support for 15 parameters? Or do you actually need this many?


And Robert said
Quote:
Correct, calling that macro creates 16 different versions of the class, so I could support from 0 to 15 parameters. If you knew that you'd ALWAYS use the ObjectFactory passing EXACTLY one constructor parameter, then you could just copy that second class instance in the text file I sent you, then the following would work fine:
ObjectFactory<Command *(int), std::string> CommandFactory;

but this would not:
ObjectFactory<Command *(int, int), std::string> CommandFactory;

Since most people would never use more than 15 parameters I decided to stick with that number, so you could create instances that pass anywhere from 0 - 15 parameters. You could use 8 if you knew you'd never pass more than 8 constructor parameters.

Rob Geiman


I sent him a final question


Another question..

And finally, your code simply doesn't work on my VC++6.0 compiler (example2), should i rebuild my 3000 line game engine to fit into VC++7.1?

I understand that 3000 lines is not a lot, but me as an amature programmer, this would be quite a daunting task.

If it is something I can fix I'll send you the errors I get when I try to compile.
--------------------Configuration: ObjectFactory - Win32 Debug--------------------Compiling...main.cppc:\documents and settings\jonathan\desktop\objectfactory\objectfactory.h(56) : error C2649: 'typename' : is not a ''c:\documents and settings\jonathan\desktop\objectfactory\objectfactory.h(56) : error C2059: syntax error : '>'c:\documents and settings\jonathan\desktop\objectfactory\objectfactory.h(57) : error C2014: preprocessor command must start as first nonwhite spacec:\documents and settings\jonathan\desktop\objectfactory\objectfactory.h(81) : error C2014: preprocessor command must start as first nonwhite spacec:\documents and settings\jonathan\desktop\objectfactory\objectfactory.h(150) : error C2992: 'ObjectFactory' : invalid or missing template parameter list        c:\documents and settings\jonathan\desktop\objectfactory\objectfactory.h(150) : see declaration of 'ObjectFactory'c:\documents and settings\jonathan\desktop\objectfactory\example2.h(17) : error C2143: syntax error : missing ';' before '<'c:\documents and settings\jonathan\desktop\objectfactory\example2.h(17) : error C2143: syntax error : missing ';' before '<'c:\documents and settings\jonathan\desktop\objectfactory\example2.h(18) : error C2146: syntax error : missing ';' before identifier 'command_factory'c:\documents and settings\jonathan\desktop\objectfactory\example2.h(18) : error C2501: 'CommandFactory' : missing storage-class or type specifiersc:\documents and settings\jonathan\desktop\objectfactory\example2.h(18) : fatal error C1004: unexpected end of file foundError executing cl.exe.Creating browse info file...BSCMAKE: error BK1506 : cannot open file '.\Debug\main.sbr': No such file or directoryError executing bscmake.exe.ObjectFactory.exe - 11 error(s), 0 warning(s)



His reply
Quote:
If I were you, I'd write all future program using VC++ 7.1. It's MUCH more C++ compliant than VC++ 6.0.

However, no reason to rewrite your current game engine. In the zip file from the tutorial there should be a VC++ 6.0 specific version of the object factory, which should compile just fine.

Rob Geiman


(I don't think he realizes that HIS VC++6 code is NOT compiling) Maybe I'm just bad at template syntax and can't see the issue..

EDIT: Lol, I challenged the programming Buddha and failed. I got errors due to overwriting the vc6 source with vc7 source and then back again to vc6 source, expecting it to work.

This is TRULY AMAZING, like, holy freakin wowazation. Its so amazing I had to make up a new word for it. Like.... Holy Grail of Object Oriented Design. And as the creator, that like, makes Robert Geiman... Like, the Jesus of OOP (or at least another high prophet or aposcle)

[Edited by - Shamino on December 16, 2005 5:28:27 PM]
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
www.thedailywtf.com
--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]

This topic is closed to new replies.

Advertisement