Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8202437
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 7, 20262026-06-07T07:11:02+00:00 2026-06-07T07:11:02+00:00

I am using x-macros to reduce the amount of repetition and code duplication while

  • 0

I am using x-macros to reduce the amount of repetition and code duplication while implementing a Lua interface for the game Bitfighter. The following code works fine:

  //                            Fn name     Valid param profiles  Profile count                           
#  define TELEPORTER_LUA_METHOD_TABLE \
      TELEPORTER_LUA_METHOD_ITEM(addDest,    ARRAYDEF({{ PT,  END }}), 1 ) \
      TELEPORTER_LUA_METHOD_ITEM(delDest,    ARRAYDEF({{ INT, END }}), 1 ) \
      TELEPORTER_LUA_METHOD_ITEM(clearDests, ARRAYDEF({{      END }}), 1 ) \


// BLOCK A Start
const luaL_reg Teleporter::luaMethods[] =
{
#  define TELEPORTER_LUA_METHOD_ITEM(name, b, c) { #name, luaW_doMethod<Teleporter, &Teleporter::name > },
      TELEPORTER_LUA_METHOD_TABLE
#  undef TELEPORTER_LUA_METHOD_ITEM
   { NULL, NULL }
};
// BLOCK A End

  /* Generates the following:
  const luaL_reg Teleporter::luaMethods[] =
  {
       { "addDest", luaW_doMethod<Teleporter, &Teleporter::addDest > }
       { "delDest", luaW_doMethod<Teleporter, &Teleporter::delDest > }
       { "clearDests", luaW_doMethod<Teleporter, &Teleporter::clearDests > }
       { NULL, NULL }
  };
  */


// BLOCK B Start
const LuaFunctionProfile Teleporter::functionArgs[] =
{
#  define TELEPORTER_LUA_METHOD_ITEM(name, profiles, profileCount) { #name, profiles, profileCount },
      TELEPORTER_LUA_METHOD_TABLE
#  undef TELEPORTER_LUA_METHOD_ITEM
   { NULL, { }, 0 }
};
// BLOCK B End


  /* Generates the following:
  const LuaFunctionProfile Teleporter::functionArgs[] =
  {
     { "addDest",    {{ PT,  END }}, 1 }
     { "delDest",    {{ INT, END }}, 1 }
     { "clearDests", {{      END }}, 1 }
     { NULL, { }, 0 }
  };
  */

#undef TELEPORTER_LUA_METHOD_TABLE

So far, so good.

Except that I do essentially the same thing in dozens of classes. What I’d REALLY like to do is define the method table in each class (which can be called anything), then define two macros that can be called like this:

GENERATE_LUA_METHODS(Teleporter, TELEPORTER_LUA_METHOD_TABLE)
GENERATE_FUNCTION_PROFILE(Teleporter, TELEPORTER_LUA_METHOD_TABLE)

to avoid all the repeated code above in blocks A & B. The obvious way is to use a nested macro, but that is, unfortunately, illegal.

Is there a better way?


SOLUTION


When I posted this question, I was pretty sure the answer would be “can’t be done.” Instead, I got two approaches, one of which was exactly what I was looking for. There was also a good discussion of the pitfalls of macros (there are many), with some alternative approaches suggested. The implementation I developed based on the accepted answer is clean and easy to understand, with the dirty macro stuff conveniently out-of-sight.

In a hidey-hole somewhere:

#define ARRAYDEF(...) __VA_ARGS__   // Don't confuse the preprocessor with array defs


////////////////////////////////////////
////////////////////////////////////////
//
// Some ugly macro defs that will make our Lua classes sleek and beautiful
//
////////////////////////////////////////
////////////////////////////////////////
//
// See discussion of this code here:
// http://stackoverflow.com/questions/11413663/reducing-code-repetition-in-c
//
// Start with a definition like the following:
// #define LUA_METHODS(CLASS, METHOD) \
//    METHOD(CLASS, addDest,    ARRAYDEF({{ PT,  END }}), 1 ) \
//    METHOD(CLASS, delDest,    ARRAYDEF({{ INT, END }}), 1 ) \
//    METHOD(CLASS, clearDests, ARRAYDEF({{      END }}), 1 ) \
//

#define LUA_METHOD_ITEM(class_, name, b, c) \
  { #name, luaW_doMethod<class_, &class_::name > },

#define GENERATE_LUA_METHODS_TABLE(class_, table_) \
  const luaL_reg class_::luaMethods[] =            \
  {                                                \
    table_(class_, LUA_METHOD_ITEM)                \
    { NULL, NULL }                                 \
  }

// Generates something like the following:
// const luaL_reg Teleporter::luaMethods[] =
// {
//       { "addDest",    luaW_doMethod<Teleporter, &Teleporter::addDest >    }
//       { "delDest",    luaW_doMethod<Teleporter, &Teleporter::delDest >    }
//       { "clearDests", luaW_doMethod<Teleporter, &Teleporter::clearDests > }
//       { NULL, NULL }
// };

////////////////////////////////////////

#define LUA_FUNARGS_ITEM(class_, name, profiles, profileCount) \
  { #name, profiles, profileCount },

#define GENERATE_LUA_FUNARGS_TABLE(class_, table_)  \
  const LuaFunctionProfile class_::functionArgs[] = \
  {                                                 \
    table_(class_, LUA_FUNARGS_ITEM)                \
    { NULL, { }, 0 }                                \
  }

// Generates something like the following:
// const LuaFunctionProfile Teleporter::functionArgs[] =
// {
//    { "addDest",    {{ PT,  END }}, 1 }
//    { "delDest",    {{ INT, END }}, 1 }
//    { "clearDests", {{      END }}, 1 }
//    { NULL, { }, 0 }
// };

////////////////////////////////////////
////////////////////////////////////////

In each class file:

//               Fn name     Param profiles       Profile count                           
#define LUA_METHODS(CLASS, METHOD) \
   METHOD(CLASS, addDest,    ARRAYDEF({{ PT,  END }}), 1 ) \
   METHOD(CLASS, delDest,    ARRAYDEF({{ INT, END }}), 1 ) \
   METHOD(CLASS, clearDests, ARRAYDEF({{      END }}), 1 ) \

GENERATE_LUA_METHODS_TABLE(Teleporter, LUA_METHODS);
GENERATE_LUA_FUNARGS_TABLE(Teleporter, LUA_METHODS);

#undef LUA_METHODS
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-07T07:11:04+00:00Added an answer on June 7, 2026 at 7:11 am

    functional approach may solve many of your woes, but you should be aware that heavy use of preprocessor leads to code that is hard to debug. you’re bound to spend much time formatting the code whenever there’s a syntax error in the generated code (and you’re bound to hit that when your macro use grows sufficiently); it’ll also impact your mood when you need to use gdb or some such.

    the following is obviously just a sketch to give you an idea.

    #  define TELEPORTER_LUA_METHOD_TABLE(class_, item) \
          item(class_, addDest,    ARRAYDEF({{ PT,  END }}), 1 ) \
          item(class_, delDest,    ARRAYDEF({{ INT, END }}), 1 ) \
          item(class_, clearDests, ARRAYDEF({{      END }}), 1 ) \
    
    #  define LUA_METHOD_ITEM(class_, name, b, c) \
      { #name, luaW_doMethod<class_, &class_::name > },
    
    #  define LUA_FUNARGS_ITEM(class_, name, profiles, profileCount) \
      { #name, profiles, profileCount },
    
    #define LUA_METHODS_TABLE(class_, table) \
      const luaL_reg class_::luaMethods[] = \
      { \
        table(class_, LUA_METHOD_ITEM) \
        { NULL, NULL } \
      };
    
    #define LUA_FUNARGS_TABLE(class_, table) \
      const LuaFunctionProfile class_::functionArgs[] = \
      { \
        table(class_, LUA_FUNARGS_ITEM) \
        { NULL, { }, 0 } \
      };
    
    LUA_METHODS_TABLE(Teleporter, TELEPORTER_LUA_METHOD_TABLE)
    
    LUA_FUNARGS_TABLE(Teleporter, TELEPORTER_LUA_METHOD_TABLE)
    
    #undef TELEPORTER_LUA_METHOD_TABLE
    

    edit to answer Watusimoto’s question from the comments.

    Watusimoto proposes something like this:

    #define LUA_METHODS_TABLE(class_) \
      const luaL_reg class_::luaMethods[] = \
      { \
        LUA_METHOD_TABLE(class_, LUA_METHOD_ITEM) \
        { NULL, NULL } \
      };
    
    #define LUA_FUNARGS_TABLE(class_, table) \
      const LuaFunctionProfile class_::functionArgs[] = \
      { \
        LUA_METHOD_TABLE(class_, LUA_FUNARGS_ITEM) \
        { NULL, { }, 0 } \
      };
    
    
    #ifdef LUA_METHOD_TABLE
    # undef LUA_METHOD_TABLE
    #endif
    
    #  define LUA_METHOD_TABLE(class_, item) \
          ... class-specific definition ...
    
    LUA_METHODS_TABLE(Teleporter)
    LUA_FUNARGS_TABLE(Teleporter)
    

    The drawback to this is that it’s not clear how is LUA_METHOD_TABLE related to the two macro calls that follow. It’s just as if sprintf(3) didn’t take arguments and instead expected the data in global variables of specific names. From the comprehensibility point of view it’s better for any piece of code to be explicit about its immediate inputs, things it works on and which are different between its uses. But the global table macro also loses on the composability front: the global macro precludes production of multiple class definitions in one go, eg. with BPP or similar.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've already implemented, using macros, a C++ property system that satisfied the following requirements:
I'm having some problems with users cheating my online game by using macros to
I've written lots of Excel macros in the past using the following development process:
I generally have ignored using macros while writing in C but I think I
Sometimes, when using macros to generate code, it is necessary to create identifiers that
I am using macros in my twig to achieve the dynamically adding rows functionality
I am trying to wrap my head around the concept of using macros to
I am working on a C math library, and it is using macros do
Is it possible to have scoped macros using custom defined macros through boost wave?
With using plain C preprocessor macros, is it possible to create something like: INIT_BASE(0x100)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.