Как сделать содержимое # include-файла постоянной времени компиляции в cpp-файле?

У меня есть файл 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 есть непереносимый способ … это было бы началом.

осветление (обновление): замена должна быть сделана во время компиляции.

9

Решение

Единственное реальное решение, которое я знаю, это написать небольшую программу, которая
преобразует файл в определение строковой переменной в C ++
содержащий его. Это довольно просто написать: выведите простой
заголовок в соответствии с:

char const variableName[] =

Затем скопируйте каждую строку файла, обернув его "...\n", а также
экранирование любых символов необходимо. (Если вы можете быть уверены в
C ++ 11, тогда вы можете сделать что-то с R"...", но
У меня нет опыта с этим.)

[обновление: ссылка на исходный вопрос с опечаткой]:
Ваше решение должно не Работа; если это так, это ошибка в
компилятор. Согласно §2.2, токенизация происходит до
выполнение директив предварительной обработки. Итак, когда
происходит выполнение директив предварительной обработки, у вас есть строка
буквально и не # токен предварительной обработки. (Ошибки компилятора
следует ожидать при использовании функций C ++ 11. Там не было
достаточно времени для разработчиков, чтобы получить все ошибки
из.)

5

Другие решения

Как взломанный только 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

Помимо внешних инструментов, я думаю, что это невозможно. C ++ 11, как вы дали, не работает, #include не раскрывается в строке. Смотрите здесь, например.

С ++ 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";
}

С GCC, ничто не считается С Visual Studio 2010, #include <string> это считается.

Если вы можете изменить цепочку компиляции, вы можете добавить шаг предварительной сборки, который будет включать в себя содержимое файла, который вы хотите, в виде строки (это можно легко сделать с помощью таких инструментов, как CMake или пользовательский make-файл).

1

Вы можете использовать ofstream, чтобы открыть поток файлов и прочитать и вывести содержимое.

0
По вопросам рекламы [email protected]