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

时间:2012-12-20 10:53:44

标签: c++ compiler-construction syntax self-modifying

我有一个文件module.hpp

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

main.cpp计划

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

我可以在...?...放置什么来打印标题文件的内容?

一个基本想法是

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

但是多行字符串仅在C ++ 11中可用,并且#include 在多行字符串中工作(这很好)?

如果gcc有一种不可移植的方式......那将是一个开始。

澄清(更新):替换应在编译时完成。

4 个答案:

答案 0 :(得分:5)

我所知道的唯一真正的解决方案是编写一个小程序 将文件转换为字符串变量的C ++定义 包含它。这写起来相当简单:输出简单 标题如下:

char const variableName[] =

然后复制文件的每一行,将其包装在"...\n"中,然后 逃避任何必要的角色。 (如果你可以肯定的话 C ++ 11,那么你可以用R"..."做一些事情,但是 我对此没有经验。)

[更新:参考原始问题中的拼写错误]: 您的解决方案应该工作;如果是的话,那是一个错误 编译器。根据§2.2,标记化在之前发生 执行预处理指令。所以当 执行预处理指令时,你有一个字符串 文字, #预处理令牌。 (编译器错误 在使用C ++ 11功能时可以预期。没有 还有足够的时间让实施者得到所有的错误 出。)

答案 1 :(得分:2)

作为仅限GNU的黑客,您可以将标头转换为二进制对象文件并将其与可执行文件链接。

首先,使用objcopy进行转换:

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

i386替换为您正在构建的体系结构(如有必要)。生成的目标文件将包含标题内容及其大小的符号,您可以按如下方式访问它们:

#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);
}

答案 2 :(得分:1)

除了外部工具,我认为无法做到。您给出的C ++ 11方式不起作用,#include未在字符串中展开。 See here for example

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,没有任何结果。使用Visual Studio 2010,#include <string>已经过时了。

如果您可以修改编译链,则可以添加预建步骤,该步骤将包含您想要的文件内容作为字符串(可以使用CMake或自定义makefile等工具轻松完成)。

答案 3 :(得分:0)

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