Как скомпоновать строку, содержащую запятую?


Я хочу передать строку версии в команде компиляции:

$ g++ -Wall -D VERSION="2013-12-03 02:15:21, commit cb060df" -o main main.cpp

В моем коде есть следующее:

#define TOSTR_(x) #x
#define STRINGIFY(x) TOSTR_(x)
#define VERSION_STR STRINGIFY(VERSION)

Это не работает, потому что макрос VERSION содержит запятую, поэтому похоже, что я передаю два аргумента в TOSTR() (очевидно, макрос VERSION расширяется только после того, как он передается в STRINGIFY() как один уникальный аргумент).

Следующий подход, который я нашел в здесь также не работает:

#define CONCAT(...) __VA_ARGS__
#define TOSTR_(x) #x
#define STRINGIFY(x) TOSTR_(CONCAT(x))
#define VERSION_STR STRINGIFY(VERSION)

Потому что это похоже на то же самое как

#define VERSIONSTR "CONCAT(2013-12-03 02:15:21, commit cb060df)"

То есть макрос CONCAT() не расширяется.

Примечание 1: я бы предпочел не передавать строку C в командной строке, потому что строка version фактически динамически генерируется, и она может содержать некоторые кавычки. Это означает, что просто написать g++ -D VERSION=""$(GENERATED_STRING)"" вместо того, чтобы строчить переданный аргумент, не будет работать. Примечание 2: я был бы очень рад, если бы кто-то нашел способ сделать это без каких-либо макросов препроцессора вообще.
2 2

2 ответа:

Вы можете написать макрос TOSTR_, чтобы принять переменные аргументы:

#define TOSTR_(x...) #x
#define STRINGIFY(x) TOSTR_(x)
#define VERSION_STR STRINGIFY(VERSION)

Этот код был протестирован и работает на Apple LLVM версии 5.0.

_ _ VA_ARGS_ _ должен быть в каждом вызове:

#define _STRINGIZE(...) #__VA_ARGS__
#define STRINGIZE(...) _STRINGIZE(__VA_ARGS__)