Pregunta

I'm trying to create a macro to replace a function definition. This macro should register the name of the function in some array so that some other macro can do something with the elements of the array.

I'd like to do this to have a list of functions that can be used in a console without having to edit the list whenever I add a new function (it's actually multiple lists).

After reading up a bit I've taken a look at the boost preprocessor. Unfortunately it appears there is no way to 'save' the new array. What I'd like to do is something like this:

#define SOME_ARRAY (0, ())
#define CONSOLE_COMMAND(a) \
  #redefine SOME_ARRAY BOOST_PP_ARRAY_PUSH_BACK(SOME_ARRAY, #a) \
  void a(some_arguments)

Unfortunately, to my knowledge, redefine doesn't exist and #define can't be used in a macro (please correct me if I'm wrong).

I took a look at boost's precompiler's SLOTs but I don't think I can change the variable in it once set either.

Is there any way to do this other than writing my own preprocessor? Is not, what would be a good start in learning how to write one? (Using MinGW with Code::Blocks).

¿Fue útil?

Solución

A common way of doing similar things is to have the functions declared in a header file using a special macro. This macro will be defined differently depending on which source file it is included in. Normally it will just define a standard function prototype, but when included in a special source file it will be defined to add entries in a table.

Something like this:

// functions.h
#ifndef FUNCTION_H_
#define FUNCTION_H_

#ifndef FUNCTION
# define FUNCTION(name) \
    void name(const std::vector<std::string> &);
#endif

FUNCTION(foo)
FUNCTION(bar)

#endif

// functions.cpp
// File that defines the function table

#include <functional>

using function_type = std::function<void(const std::vector<std::string> &)>;

#define FUNCTION(name) \
    { #name, name },

std::map<std::string, function_type> functions = {
#include "functions.h
};

Now you have a std::map containing pointers to the functions, indexed by the function name.

Yes you still have to maintain a "list" of your functions, namely the prototype list in functions.h, but when you add (or remove) functions it's very easy to "modify" this list.

Otros consejos

The preprocessor isn't designed to be able to redefine symbols, so you can't use it to accumulate a value in a pass through the file.

One possible solution would be to use a redefinition and self-reinclude as an X-Macros technique:

#define CONSOLE_COMMAND(a,body) \
    void a(some_arguments) body

CONSOLE_COMMAND(my_command, { ... })

const char *array[] = {
#undef CONSOLE_COMMAND
#define CONSOLE_COMMAND(a,body) #a ,
#include __FILE__
};

A more idiomatic C++ solution would be to have your commands as file-scope objects whose constructors register them at program startup time.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top