简体   繁体   English

如何在#cc文件中使#include-file的内容成为编译时常量?

[英]How can I make the contents of an #include-file a compile-time constant in a cpp-file?

I have a file module.hpp 我有一个文件module.hpp

struct ModuleBase {
    virtual void run() = 0;
};

and a main.cpp program 和一个main.cpp程序

int main() {
    cout << ...?...; // here should go the contents of module.hpp
}

What can I put at ...?... to let the contents of the header file printed here? 我可以放什么...?...让头文件的内容打印在这里?

A basic idea would be 一个基本的想法是

int main() {
    static const string content = R"(
#include <module.hpp>
)";
    cout << content;
}

but multi-line-strings are only available in C++11, and #include does not work inside multi-line strings (which is good)? 但多线串仅在C ++ 11可用, #include 并不多行字符串内工作(这是很好的)?

If there is a non-portable way for the gcc... that would be a start. 如果gcc有一个不可移植的方式......那将是一个开始。

Clarification (update): The substitution should be done at compile time. 澄清 (更新):替换应在编译时完成。

The only real solution I know is to write a small program which converts a file into a C++ definition of a string variable containing it. 我所知道的唯一真正的解决方案是编写一个小程序,将文件转换为包含它的字符串变量的C ++定义。 This is fairly simple to write: output a simple header along the lines of: 这写起来相当简单:输出一个简单的标题:

char const variableName[] =

Then copy each line of the file, wrapping it in "...\\n" , and escaping any characters necessary. 然后复制文件的每一行,将其包装在"...\\n" ,并转义所需的任何字符。 (If you can be sure of C++11, then you might be able to do something with R"..." , but I've no experience with this.) (如果你能确定C ++ 11,那么你可以用R"..."做一些事情,但我对此没有经验。)

[update: refering to the original question with a typo in it]: Your solution should not work; [更新时间:指的在这一个错字原题]:您的解决方案应该工作; if it does, it is an error in the compiler. 如果是,则编译器中出错。 According to §2.2, tokenization occurs before the execution of preprocessing directives. 根据§2.2,标记化发生执行预处理指令之前。 So when the execution of preprocessing directives occurs, you have a string literal, and not a # preprocessing token. 因此,当执行预处理指令时,您有一个字符串文字,而不是 #预处理标记。 (Compiler errors are to be expected when using C++11 features. There's not been enough time yet for the implementers to get all of the bugs out.) (使用C ++ 11功能时会出现编译器错误。实施者还没有足够的时间来解决所有错误。)

As a GNU-only hack, you could convert the header into a binary object file and link that with the executable. 作为仅限GNU的黑客,您可以将标头转换为二进制对象文件并将其与可执行文件链接。

First, use objcopy to do the conversion: 首先,使用objcopy进行转换:

objcopy -I binary -O default -B i386 module.hpp module.hpp.o 

replacing i386 with the architecture you're building for if necessary. 如有必要,用您正在构建的架构替换i386 The resulting object file will contain symbols for the header contents and its size, which you can access as follows: 生成的目标文件将包含标题内容及其大小的符号,您可以按如下方式访问它们:

#include <iostream>

extern char _binary_module_hpp_start;
extern char _binary_module_hpp_size;

int main()
{
    char * header_start = &_binary_module_hpp_start;
    size_t header_size = reinterpret_cast<size_t>(&_binary_module_hpp_size);

    std::cout.write(header_start, header_size);
}

Apart from external tools, I think it cannot be done. 除了外部工具,我认为无法做到。 The C++11 way you given does not work, #include is not expanded in a string. 你给出的C ++ 11方法不起作用, #include不会在字符串中展开。 See here for example . 例如,见这里

The C++03 way would have been the following, with macros: 在C ++ 03的方式将是下文中,宏:

#define TO_STR__(...) #__VA_ARGS__
#define TO_STR_(...) TO_STR__(__VA_ARGS__)
#define TO_STR(...) TO_STR_(__VA_ARGS__)

#include <iostream>
int main()
{
    std::cout << "String from #include <string>, ";
    static const char* str = TO_STR(
#include <string>
    );

    std::cout << sizeof(str) / sizeof(char) << " characters:\n\n";
    std::cout << str << "\n";
}

With GCC , nothing is outputed. 有了海湾合作委员会 ,没有任何事情可以说明 With Visual Studio 2010, #include <string> is outputed. 使用Visual Studio 2010, #include <string>已输出。

If you can modify the compilation chain, you can add a prebuild step which will include the contents of the file you want as a string (can be done easily with tools like CMake, or custom makefile). 如果您可以修改编译链,则可以添加预构建步骤,该步骤将包含您想要的文件内容作为字符串(可以使用CMake或自定义makefile等工具轻松完成)。

您可以使用ofstream打开文件流并读取和输出内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM