4

I have a text file containing resources my application needs. The file contains arbitrary plain text, not C++ code with variable assignments. I don't want to ship the text file along with my application; I'd prefer to compile it into it. So I tried the following:

#include <iostream>
#include <string>

int main() {
    std::string test = R"(
#include <textresource.txt>
)";
    std::cerr << test << std::endl;
}

I expected the #include in line 6 to be executed at preprocessing time, getting replaced with the contents of the resource file. After that, the compiler would see a raw string literal with the resource data.

However, the output is simply the text #include <textresource.txt> with newlines around it. So apparently, the #include is never executed. (I'm using Visual Studio 2015.)

Why doesn't the #include work as expected? Is there some other syntax that will import a text file (not code) into a variable at compile time?

Daniel Wolf
  • 12,855
  • 13
  • 54
  • 80
  • Very similar question, albeit for C: http://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char – Tony Delroy May 18 '16 at 07:24

2 Answers2

4

Why doesn't the #include work as expected?

The C++ Standard's 2.2 Phases of Translation lists steps:

  1. The source file is decomposed into preprocessing tokens (2.4)...

(and under 2.4 Preprocessing Tokens you'll find string-literals is one of the token types)

  1. Preprocessing directives are executed

So your string literal incorporating the text "#include..." is correctly tokenised as a string literal, rather than anything subject to preprocessing directive execution.

Is there some other syntax that will import a text file (not code) into a variable at compile time?

Not in the C++ language proper. You can of course orchestrate this in your build system... invoking some shell or utility program to stitch together the C++ source code you want. Specific C++ compilers may offer non-Standard facilities to facilitate this; you'll need to check the docs for the compilers you're interested in.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Thanks for the detailed answer and the quotes from the standard. That makes perfect sense and explains the results I got. I could have sworn preprocessing directives were executed prior to tokenization. My bad! – Daniel Wolf May 18 '16 at 08:09
0

I am not sure what is content of textresource.txt. But you can do like this.

File textresource.c

#include <string>
static std::string myString {"Very large string content ........ you may be need proper escape character depending on your content."};

File main.cpp

#include <iostream>
#include <string>
#include "textresource.c"
int main() {
    std::string test = myString;
    std::cerr << test << std::endl;
}
Manthan Tilva
  • 3,135
  • 2
  • 17
  • 41
  • I realize I can put the data into a string literal, then import that. The point of my question is that I'm trying to use the preprocessor to generate this literal for me. I've edited the question to make it clear that the resource file contains arbitrary text, *not* code. – Daniel Wolf May 18 '16 at 07:06
  • Okay. As answered by Tony D above, you can't do this as it is, but you must do some hack in your build system so it can provide content of file into some variable. – Manthan Tilva May 18 '16 at 07:38