[英]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.