Can I split a long #include directive into two lines?
Asked Answered
C

5

20

I wish there was a way to split a #include directive across two lines, so that my code can conform to 80 characters per line, despite the necessity of a very long include path.

Other than expanding the search path of the compiler, how can I manage this? Is there a way to split my very long path string into two lines?

"#define" macro expansion apparently happens after #include expansion, so these don't work:

#define BIGPATH "..."
#include BIGPATH ## "/foo.c"
#include "BIGPATH/foo.c"
#include BIGPATH"/foo.c"

I've also tried

#include "foo" ##
         "bar"

and

#include "foo" \
         "bar"

To no avail. Perhaps what I want is impossible? Help me, stackoverflow kenobi, you're my only hope.

ANSWER: building on the suggested answer below, here's what actually worked for me:

#define STRINGIFY(x) #x
#define PATH(path) STRINGIFY(/my/very/long/path)
#include PATH(foo.h)
#undef PATH
#undef STRINGIFY
Conjugate answered 4/10, 2012 at 19:3 Comment(4)
Symlink your target directory to something that fits on one line. Or, set up the include path so that you only need the file name, not the entire path. (And you can't do what you want with the preprocessor, that doesn't preprocess preprocessor directives.)Demount
Macro expansion happens before include expansion, otherwise #include SOME_ARG_FROM_USER (e.g. in Boost.Preprocessor) wouldn't work.Propitious
Long absolute fixed path are ugly, prefer instead passing it as argument to the preprocessor, it will be much more flexible and will give you less troubles the day the path hanges ... e.g. check the -I option of gccCommix
Avakar's comment on one of the answers implies that your third one is almost correct - try #include "foo\ (newline, and no preceding whitespace on the next line) bar", and post it as a possible answer if it does.Gnathic
M
12

I do not like the idea of this, I just wanted to mention this possibility. The best is to go the way Daniel Fischer mentioned. This solution is a bit quirky and will not work under all circumstances but this compiled here:

#define PATH(FILE) </path/to/FILE>
#include PATH(file.h)

And just to name some of the obvious limitations:

  • the search path of these includes is not "local"
  • FILE must not contain "," (rather uncommon)
  • the PATH define can still exceed 80 characters

Feel free to add to this list.

Edit
Just for better readability I will post the solution from Jonathans comment below in the style of my example:

#define STRINGIFY(x) #x 
#define PATH(FILE) STRINGIFY(/path/to/FILE) 
#include PATH(foo.h)

This version mitigates the "locality problem" of the #include <> version, as it maps to #include ""

Motionless answered 4/10, 2012 at 19:20 Comment(2)
This came closest, but I had to modify slightly for my needs: #define STRINGIFY(x) #x #define PATH(path) STRINGIFY(/my/very/long/path) #include PATH(foo.h) #undef PATH #undef STRINGIFYConjugate
@JonathanMayer Post an answer your self if that's what worked for you instead of editing different answers. (You can accept your own if you prefer)Peptidase
P
9

This compiles for me (I'm basing it off of how I recall Boost.PP working):

#define a() <vec\
tor>

#include a()

int main() {
  std::vector<int> x;
}

Just change <vector> to your full path - I don't think you can concatenate strings the way you need to in #include.

Peptidase answered 4/10, 2012 at 19:15 Comment(0)
T
4

Use another header file with a short name to store header files with long names. So all headers that exceed you 80 character minimum is not in you nicely formatted code.

//short_name.h
#include "really_really_long_include_name.h"

//code
#include "short_name.h"
Trifoliate answered 4/10, 2012 at 19:19 Comment(0)
A
4

All preprocessing directives are terminated by a new-line token. The include directive is of one of the following forms:

# include < h-char-sequence> new-line
# include " q-char-sequence" new-line
# include pp-tokens new-line

Your final example will result in the equivalent of #include "foo" "bar" being executed because, although the escaped new line deletion will occur before directive execution, string concatenation occurs afterwards. This matches the final valid form of an include directive.

However, what happens with this form is that any macro names following include will be replaced. Yours doesn't have any macros. If the resulting directive doesn't match either of the normal two forms, the behaviour is undefined.

If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined

The standard has a specific note about the case where there are multiple string literals:

Note that adjacent string literals are not concatenated into a single string literal (see the translation phases in 2.2); thus, an expansion that results in two string literals is an invalid directive.

So that's why that example doesn't work. It does however mean that we can rely on macro expansion to generate a valid filename. For example:

#define LONG_PATH(file) <foo/bar/baz/file>
#include LONG_PATH(file.h)

Or:

#define STRINGIZE(x) #x
#define LONG_PATH(file) STRINGIZE(foo/bar/baz/file)
#include LONG_PATH(file.h)
Azaleah answered 4/10, 2012 at 19:31 Comment(1)
Do macros expand inside string literals?Motionless
U
3

No, you can't, the preprocessor requires the include filename to be a single preprocessing token. You need to either fix the include search path you're using, or relax the requirement of 80 characters per line.

Ultann answered 4/10, 2012 at 19:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.