Is there a way to pull in a text resource into a raw string literal using the pre-processor?

浪子不回头ぞ 提交于 2019-11-28 04:47:33

问题


I've just noticed that an answer I have given for this question actually doesn't work:

Regardless of using CMake or not, the following should work with the current standard:

std::string resource = R"(
#include "text.txt"
)";

I thought that the pre-processor would recognize the #include "text.txt" statement in first place and expand the text.

But that's obviously not the case, the result for

std::cout << resource << std::endl;

is

#include "text.txt"

I tried to use some macro to let the #include statement be expanded within, but it doesn't work either:

#include <string>
#include <iostream>

#define RESOURCE_DEFINIION(resource_var,resource_name) \
    const std::string resource_var = R"xxx( \
    #include resource_name \
    )xxx";

RESOURCE_DEFINIION(resource,"text.txt")

int main()
{
   std::cout << resource << std::endl; 

   return 0;
}

The output is

\                                                                                                                                                                                          
    #include resource_name \                                                                                                                                                                

Here's the demo to play with


Is there any trickery available to pull in the text.txt resource into a c++-11 raw-string literal, using the pre-processor or any other regular c++ language feature?


Disclaimer:

I well know what's wrong with the above samples and why these fail this way. It's a problem that the pre-processor ignores the stuff appearing within " pairs.

So is there a way to escape these to be seen by the pre-processor?


回答1:


It seems like not possible in standard C++

Problem 0: Only standard way of textual inclusion is #include directive.

Problem 1: String literal is a preprocessing token, which are recognised in phase 3, so when preprocessing directives are executed in phase 4, it is already determined that #include is a part of string literal and not a preprocessing directive.

preprocessing-token:
    header-name
    identifier
    pp-number
    character-literal
    user-defined-character-literal
    string-literal
    user-defined-string-literal
    preprocessing-op-or-punc
    each non-white-space character that cannot be one of the above

Problem 2: It is impossible to bring preprocessing directive in source and execute it by macro substitution:

16.3.4/3
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one

So you cannot have working #include inside macro.

Problem 3: macro replacement list should be a valid preprocessing token:

control-line:
    # define identifier replacement-list new-line
replacement-list:
        pp-tokens opt
pp-tokens:
    preprocessing-token
    pp-tokens preprocessing-token

And string literal is a preprocessing token itself, you cannot build string literal from several macro.



来源:https://stackoverflow.com/questions/37622767/is-there-a-way-to-pull-in-a-text-resource-into-a-raw-string-literal-using-the-pr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!