Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic #include based on macro definition

I'm writing a C++ application in which I want to let the developer choose what algorithm to use for a particular problem at compile time. Both algorithms are implemented as C++ classes that implement a common interface, and are drop-in replacements for each other. They both have a .h and a .cpp file, and reside in a subdirectory (let's call it impl/).

In my Makefile, I have something along the lines of this:

...
IMPL = default
...
binary: ... impl/$(IMPL).o
...
impl/%.o: impl/%.cpp impl-interface.h impl/%.h
...
%o: %.cpp ...
    $(CXX) $(CXXFLAGS) -DIMPL=$(IMPL) -c -o $@ $*.cpp

The idea is that the user should be able to type make binary IMPL=thatimpl.

In whatever files wants to use the algorithm the user has chosen, I then do:

IImpl o = new IMPL();

However, this requires me to include the header file for the chosen implementation. Unfortunately, C++ requires #include to be followed by either a "string", a <libfile>. You can also use a macro as suggested here, but it requires the argument to the macro to be a literal string. If I use:

#define QUOTEME(M)       #M
#define INCLUDE_FILE(M)  QUOTEME(impl/##M##.h)
#include INCLUDE_FILE(IMPL)

The compiler will try to include the literal string impl/IMPL.h, rather than expanding IMPL to whatever was passed to make and then to the compiler.

Any pointers on how I might achieve this would be very welcome!

like image 691
Jon Gjengset Avatar asked Jan 08 '14 13:01

Jon Gjengset


1 Answers

You just need to add an extra layer of indirection, because of the way the preprocessor works. This should do:

#define QUOTEME(x) QUOTEME_1(x)
#define QUOTEME_1(x) #x
#define INCLUDE_FILE(x) QUOTEME(impl/x.h)

#include INCLUDE_FILE(IMPL)

Live example

like image 135
Angew is no longer proud of SO Avatar answered Oct 01 '22 17:10

Angew is no longer proud of SO