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>