Home > Software engineering >  Using macros to define forward declarations
Using macros to define forward declarations

Time:10-13

I am writing a pretty huge program with lots of templated functions. Naturally, the program has a long compile-time, which is why I wanted to use forward declaration. Now there are a lot of functions and I do not want to write the forward declaration for each single one of them. Even more so, I want to be able to add some functions without having to add the forward declarations manually.

A quick example:

#define max_dim 3
template bool match_any<1>();
template bool match_any<2>();
template bool match_any<3>();

If I set max_dim to another value, I do not want to manually add the additional forward declarations. Until now I have used a python-script, to just generate a file with all the forward declarations for me.

My goal now is to avoid the python-script and to do this using the cpp-preprocessor only (if this is possible). More concretly, I want to be able to just change the max_dim and all neccessary forward-declarations are generated.

I now that loops etc. are possible just with the preprocessor; what I do not know is how to actually make the preprocessor generate the declarations.

CodePudding user response:

I'm not the right one to ask if what you want to do is possible in a better way, but this is definitely solvable using the preprocessor.

I'll use file iteration, although other methods are also possible:

// slot.h
#ifndef A_0
# include "a.h"
#else
# include "b.h"
#endif


// a.h
#if (SLOT) & 1
# define A_0 1
#else
# define A_0 0
#endif
#if (SLOT) & 2
# define A_1 2
#else
# define A_1 0
#endif
#if (SLOT) & 4
# define A_2 4
#else
# define A_2 0
#endif
#if (SLOT) & 8
# define A_3 8
#else
# define A_3 0
#endif

#undef VAL
#define VAL (A_3|A_2|A_1|A_0)

#undef B_0
#undef B_1
#undef B_2
#undef B_3


// b.h
#if (SLOT) & 1
# define B_0 1
#else
# define B_0 0
#endif
#if (SLOT) & 2
# define B_1 2
#else
# define B_1 0
#endif
#if (SLOT) & 4
# define B_2 4
#else
# define B_2 0
#endif
#if (SLOT) & 8
# define B_3 8
#else
# define B_3 0
#endif

#undef VAL
#define VAL (B_3|B_2|B_1|B_0)

#undef A_0
#undef A_1
#undef A_2
#undef A_3



// impl.cpp
#ifndef VAL
#define VAL 12
#endif

template bool match_any<VAL>();

#define SLOT (VAL-1)
#include "slot.h"
#if VAL != 0
#include __FILE__
#endif

(https://godbolt.org/z/csehns44j)

If you need more than 4 bits to represent the value of max_dim, then you'd need to add a few lines to a.c and b.c. This uses self recursive includes, which only works for a few hundred iterations (without special compiler flags). To circumvent this, you can use the following structure:

// iter1.h
#if CONTINUE
#include "iter2.h"
#if CONTINUE
#include "iter2.h"
#if CONTINUE
#include "iter2.h"
#if CONTINUE
#include "iter2.h"
#if CONTINUE
#include "iter2.h"
// ...
#endif
#endif
#endif
#endif
#endif

// iter2.h
#if CONTINUE
#include "iter3.h"
#if CONTINUE
#include "iter3.h"
#if CONTINUE
#include "iter3.h"
#if CONTINUE
#include "iter3.h"
#if CONTINUE
#include "iter3.h"
// ...
#endif
#endif
#endif
#endif
#endif

// iter3.c
#if CONTINUE
#include FILE
#if CONTINUE
#include FILE
#if CONTINUE
#include FILE
#if CONTINUE
#include FILE
#if CONTINUE
#include FILE
// ...
#endif
#endif
#endif
#endif
#endif



// impl.cpp
#ifndef VAL
#define VAL 100
#define FILE "impl.cpp"
#endif

template bool match_any<VAL>();

#define SLOT (VAL-1)
#define CONTINUE VAL != 0
#include "slot.h"

#ifndef ONCE
#define ONCE
#include "iter1.h"
#endif

(https://godbolt.org/z/h74jPb11c)

With 3 iter.h files, of which each has 5 includes that results in 5^3 iterations. Expanding this should be trivial.

CodePudding user response:

It is doubtful if the idea below is an improvement for you, but here is how it could be done.

// in some header file:
#define MAX_DIM 3
#ifndef __INSTANCE_IMPL
#  define TINSTANCE(n) \
   extern template bool match<(n)>;
#else
#  define TINSTANCE(n) \
   template bool match<size_t N = (n)> {
     // however it is implemented
   }
#endif

TINSTANCE(1)
TINSTANCE(2)
TINSTANCE(3)

// in the .cpp file:
#define __INSTANCE_IMPL
#include <extra-header>
  • Related