Lots of Macros, can someone explain what these do?

Started by
14 comments, last by Arild Fines 18 years, 4 months ago
Whole bunch of macro's ment for repeating code

///////////////////////////////////////////////////////////////////////////////
// 
// MacroRepeat
// 
// This header provides macros for repeating code.
// 
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 Robert Geiman.
//
// Permission to copy, modify, and use this code for personal and commercial
// software is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without any expressed or implied warranty.
//
// Any comments or questions can be sent to: rgeiman@buckeye-express.com
//
///////////////////////////////////////////////////////////////////////////////

#ifndef MACRO_REPEAT_H
#define MACRO_REPEAT_H


///////////////////////////////////////////////////////////////////////////////
// The MACRO_EMPTY_SEPERATOR should be left empty, but Visual C++ 6.0 chokes on
// passing empty defines to macros, so to get around deficiency we define this
// macro as an empty comment section (/**/).  Note that this is NOT valid with
// a standard compliant compiler 
///////////////////////////////////////////////////////////////////////////////
#define MACRO_EMPTY_SEPERATOR /##**/
#define MACRO_COMMA_SEPERATOR ,
#define MACRO_SEMICOLAN_SEPERATOR ;
#define MACRO_BEGIN_PAREN_SEPERATOR (
#define MACRO_END_PAREN_SEPERATOR )


#define MACRO_EMPTY_MACRO(num)
#define MACRO_TEMPLATE_PARAMETER(num) typename A##num
#define MACRO_TEMPLATE_ARGUMENT(num) A##num
#define MACRO_FUNCTION_PARAMETER(num) A##num a##num
#define MACRO_FUNCTION_ARGUMENT(num) a##num


#define MACRO_REPEAT_0(begin_seperator, seperator, macro, end_seperator) 
#define MACRO_REPEAT_1(begin_seperator, seperator, macro, end_seperator) begin_seperator macro(0) end_seperator
#define MACRO_REPEAT_2(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_1(begin_seperator, seperator, macro, end_seperator) seperator macro(1) end_seperator
#define MACRO_REPEAT_3(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_2(begin_seperator, seperator, macro, end_seperator) seperator macro(2) end_seperator
#define MACRO_REPEAT_4(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_3(begin_seperator, seperator, macro, end_seperator) seperator macro(3) end_seperator
#define MACRO_REPEAT_5(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_4(begin_seperator, seperator, macro, end_seperator) seperator macro(4) end_seperator
#define MACRO_REPEAT_6(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_5(begin_seperator, seperator, macro, end_seperator) seperator macro(5) end_seperator
#define MACRO_REPEAT_7(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_6(begin_seperator, seperator, macro, end_seperator) seperator macro(6) end_seperator
#define MACRO_REPEAT_8(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_7(begin_seperator, seperator, macro, end_seperator) seperator macro(7) end_seperator
#define MACRO_REPEAT_9(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_8(begin_seperator, seperator, macro, end_seperator) seperator macro(8) end_seperator
#define MACRO_REPEAT_10(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_9(begin_seperator, seperator, macro, end_seperator) seperator macro(9) end_seperator
#define MACRO_REPEAT_11(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_10(begin_seperator, seperator, macro, end_seperator) seperator macro(10) end_seperator
#define MACRO_REPEAT_12(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_11(begin_seperator, seperator, macro, end_seperator) seperator macro(11) end_seperator
#define MACRO_REPEAT_13(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_12(begin_seperator, seperator, macro, end_seperator) seperator macro(12) end_seperator
#define MACRO_REPEAT_14(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_13(begin_seperator, seperator, macro, end_seperator) seperator macro(13) end_seperator
#define MACRO_REPEAT_15(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_14(begin_seperator, seperator, macro, end_seperator) seperator macro(14) end_seperator
#define MACRO_REPEAT_16(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_15(begin_seperator, seperator, macro, end_seperator) seperator macro(15) end_seperator
#define MACRO_REPEAT_17(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_16(begin_seperator, seperator, macro, end_seperator) seperator macro(16) end_seperator
#define MACRO_REPEAT_18(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_17(begin_seperator, seperator, macro, end_seperator) seperator macro(17) end_seperator
#define MACRO_REPEAT_19(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_18(begin_seperator, seperator, macro, end_seperator) seperator macro(18) end_seperator
#define MACRO_REPEAT_20(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_19(begin_seperator, seperator, macro, end_seperator) seperator macro(19) end_seperator
#define MACRO_REPEAT_21(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_20(begin_seperator, seperator, macro, end_seperator) seperator macro(20) end_seperator
#define MACRO_REPEAT_22(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_21(begin_seperator, seperator, macro, end_seperator) seperator macro(21) end_seperator
#define MACRO_REPEAT_23(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_22(begin_seperator, seperator, macro, end_seperator) seperator macro(22) end_seperator
#define MACRO_REPEAT_24(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_23(begin_seperator, seperator, macro, end_seperator) seperator macro(23) end_seperator
#define MACRO_REPEAT_25(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_24(begin_seperator, seperator, macro, end_seperator) seperator macro(24) end_seperator
#define MACRO_REPEAT_26(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_25(begin_seperator, seperator, macro, end_seperator) seperator macro(25) end_seperator
#define MACRO_REPEAT_27(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_26(begin_seperator, seperator, macro, end_seperator) seperator macro(26) end_seperator
#define MACRO_REPEAT_28(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_27(begin_seperator, seperator, macro, end_seperator) seperator macro(27) end_seperator
#define MACRO_REPEAT_29(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_28(begin_seperator, seperator, macro, end_seperator) seperator macro(28) end_seperator
#define MACRO_REPEAT_30(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_29(begin_seperator, seperator, macro, end_seperator) seperator macro(29) end_seperator
#define MACRO_REPEAT_31(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_30(begin_seperator, seperator, macro, end_seperator) seperator macro(30) end_seperator
#define MACRO_REPEAT_32(begin_seperator, seperator, macro, end_seperator) MACRO_REPEAT_31(begin_seperator, seperator, macro, end_seperator) seperator macro(31) end_seperator


#define MACRO_LIST(num, macro) MACRO_REPEAT_##num(MACRO_EMPTY_SEPERATOR, MACRO_COMMA_SEPERATOR, macro, MACRO_EMPTY_SEPERATOR)
#define MACRO_LIST_APPEND(num, macro) MACRO_REPEAT_##num(MACRO_COMMA_SEPERATOR, MACRO_COMMA_SEPERATOR, macro, MACRO_EMPTY_SEPERATOR)
#define MACRO_LIST_PREPEND(num, macro) MACRO_REPEAT_##num(MACRO_EMPTY_SEPERATOR, MACRO_COMMA_SEPERATOR, macro, MACRO_COMMA_SEPERATOR)
#define MACRO_BEGIN_PAREN(num, macro) MACRO_REPEAT_##num(MACRO_BEGIN_PAREN_SEPERATOR, MACRO_EMPTY_SEPERATOR, macro, MACRO_EMPTY_SEPERATOR)
#define MACRO_END_PAREN(num, macro) MACRO_REPEAT_##num(MACRO_END_PAREN_SEPERATOR, MACRO_EMPTY_SEPERATOR, macro, MACRO_EMPTY_SEPERATOR)
#define MACRO_REPEAT(num, macro) MACRO_REPEAT_##num(MACRO_EMPTY_SEPERATOR, MACRO_EMPTY_SEPERATOR, macro, MACRO_EMPTY_SEPERATOR)



#endif

And here is how they're implemented

#define OBJECT_FACTORY(num)                                                                                 
   template<typename BaseClassType MACRO_LIST_APPEND(num, MACRO_TEMPLATE_PARAMETER), typename UniqueIdType> 
   class ObjectFactory##num                                                                                 
   {                                                                                                        
   protected:                                                                                               
      class CreateObjectBase                                                                                
      {                                                                                                     
      public:                                                                                               
         virtual ~CreateObjectBase() {}                                                                     
         virtual BaseClassType *operator()(MACRO_LIST(num, MACRO_FUNCTION_PARAMETER)) = 0;                  
      };                                                                                                    
                                                                                                            
      template<typename ClassType>                                                                          
      class CreateObject : public CreateObjectBase                                                          
      {                                                                                                     
      public:                                                                                               
         BaseClassType *operator()(MACRO_LIST(num, MACRO_FUNCTION_PARAMETER))                               
         {                                                                                                  
			return new ClassType MACRO_BEGIN_PAREN(num, MACRO_EMPTY_MACRO) MACRO_LIST(num, MACRO_FUNCTION_ARGUMENT) MACRO_END_PAREN(num, MACRO_EMPTY_MACRO);
         }                                                                                                  
      };                                                                                                    
                                                                                                            
   public:                                                                                                  
      typedef typename std::map<UniqueIdType, CreateObjectBase*>::const_iterator ConstIterator;             
      typedef typename std::map<UniqueIdType, CreateObjectBase*>::iterator Iterator;                        
                                                                                                            
      ~ObjectFactory##num()                                                                                 
      {                                                                                                     
         Iterator iter = m_object_creator.begin();                                                          
                                                                                                            
         while (iter != m_object_creator.end())                                                             
         {                                                                                                  
            delete (*iter).second;                                                                          
            ++iter;                                                                                         
         }                                                                                                  
      }                                                                                                     
                                                                                                            
      template<typename ClassType>                                                                          
      bool Register(UniqueIdType unique_id, Type2Type<ClassType>)                                           
      {                                                                                                     
         if (m_object_creator.find(unique_id) != m_object_creator.end())                                    
            return false;                                                                                   
                                                                                                            
         m_object_creator[unique_id] = new CreateObject<ClassType>;                                         
                                                                                                            
         return true;                                                                                       
      }                                                                                                     
                                                                                                            
      bool Unregister(UniqueIdType unique_id)                                                               
      {                                                                                                     
         Iterator iter = m_object_creator.find(unique_id);                                                  
                                                                                                            
         if (iter != m_object_creator.end())                                                                
         {                                                                                                  
            delete (*iter).second;                                                                          
            m_object_creator.erase(iter);                                                                   
                                                                                                            
            return true;                                                                                    
         }                                                                                                  
                                                                                                            
         return false;                                                                                      
      }                                                                                                     
                                                                                                            
      BaseClassType *Create(UniqueIdType unique_id MACRO_LIST_APPEND(num, MACRO_FUNCTION_PARAMETER))        
      {                                                                                                     
         Iterator iter = m_object_creator.find(unique_id);                                                  
                                                                                                            
         if (iter == m_object_creator.end())                                                                
            return NULL;                                                                                    
                                                                                                            
         return ((*iter).second)->operator()(MACRO_LIST(num, MACRO_FUNCTION_ARGUMENT));                     
      }                                                                                                     
                                                                                                            
      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, CreateObjectBase*> m_object_creator;                                           
   };                                                                                                       

MACRO_REPEAT(16, OBJECT_FACTORY)
#undef OBJECT_FACTORY

#endif

Can someone like, cut lines and snippets out of the implementation and write out longhand what you would put instead of the macro? I'm very unfamiliar with macro's and exactly how to declare them and how to use them n stuff, thanks.
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
Advertisement
I just want to say thats some of the ugliest macroing Ive seen - good luck on deciphering it. Damn you Robert Geiman! You could always email this guy and ask him, seeing how all the macros seem to be undocumented in code. ALl I can tell you is that they apparently repeat something.
Well that's comforting :\
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
The macros are in fact an unrolled recursive definition. It says that, to repeat "FOO" X times,
- if X=1 then you write "FOO"
- otherwise, you repeat "FOO" (X-1) times, then you write "FOO"

With some additional information (like repeating slightly different things each time by writing FOO(X) instead of FOO, which assumes FOO is a macro), and separators.

In the end, it uses ## to transform a numeric argument into a hardcoded macro name corresponding with a given amount of repetitions. This results in:

MACRO_REPEAT(num,macro)

Being evaluated to:

macro(num-1) macro(num-2) ... macro(0)

Which in turn is evaluated into whatever macro becomes. This is truly ugly, by the way.
Lol, if I could get him to rewrite it without the macro's do you think I could understand what the fudge that template does?
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
Quote:Original post by Shamino
Can someone like, cut lines and snippets out of the implementation and write out longhand what you would put instead of the macro? I'm very unfamiliar with macro's and exactly how to declare them and how to use them n stuff, thanks.
Most compilers can do this for you. Check your compiler's options, there should be one for invoking the preprocessor separately.
The output will probably be huge and generally unmaintainable though, so you probably want to keep the macros around and just use the preprocessor output for debugging purposes.
He's pretty much trying to repeat a macro (that takes a number as an argument) some number of times, and expanding them in increasing order (not decreasing)

For example:

#define MY_NUM(n) n
MACRO_REPEAT(MY_NUM, 5)

Will result in something like

"MY_NUM(0) MY_NUM(1) ... MY_NUM(4)"

which then translates into

"0 1 ... 4"

No, he goes the extra step and adds seperators and stuff into that, so that he can generate parameter lists. Notice the "begin_seperator, seperator, macro, end_seperator" stuff? That's just dictates what needs to go between the generated macros. For example, if I did the following

MACRO_LIST(MY_NUM, 5)

it'll translate into "0, 1, 2, 3, 4", since the macro uses no begin and end seperators, but just shoves a comma between the 'terms' I guess you could say.

The other macros use variations of the repeat macro to constructed lists and nested lists, though they look like they need to be used in conjunction with one another.

Blegh. That's real nasty. I have no real problem with macros when used "correctly", but that's just plain old crazy.

Edit:

Oh, and as far as the class is concerned, he's just trying to make a bunch of factories for some object type (which gets registered at some point by the factory itself). I guess he ended up having to write a lot of duplicate factories that look "almost" the same for similar objects (maybe?), and got tired of it. His final goal you can see at the bottom when he does this:

"MACRO_REPEAT(16, OBJECT_FACTORY)"

He wants to make 16 factories, and wants to be able to quickly change that number whenever he feels frisky.

*shrugs*
Quote:"MACRO_REPEAT(16, OBJECT_FACTORY)"

He wants to make 16 factories, and wants to be able to quickly change that number whenever he feels frisky.

*shrugs*


Actually that cleared that up alot..
Question though, why does he need 16 factories?
----------------------------------------------------------Rating me down will only make me stronger.----------------------------------------------------------
Quote:Original post by Shamino
Question though, why does he need 16 factories?
To forward a variable number of parameters to the templated class's constructor.
Yes, it's an ugly hack. But it's the best solution the language provides to the forwarding problem.

Take a look at boost::preprocessor for further details, it's basically just an advanced version of the code above but at least it's decently documented.

This topic is closed to new replies.

Advertisement