Напишите макрос для преобразования содержимого структуры в строку.

Я пытаюсь написать макрос для расширения содержимого структуры:

struct Str
{
    int a;
    float f;
    char *c;
};
Str s = {123, 456.789f, "AString"};

#define STRINGIFY_STR(x) ... // Macro to stringify x which is an instance of Str

printf("%s", STRINGIFY_STR(s));

желаемый результат: [a: 123, f: 456,789, c: AString]

Можно ли написать макрос, который это делает? Если да, то как?


person FearLeslie    schedule 16.06.2012    source источник
comment
натягивать? макросы? Почему бы просто не добавить метод toString к вашему объекту или бесплатную функцию, которая принимает константную ссылку для достижения этой цели? Вы даже можете просто использовать std::ostringstream, если производительность не имеет значения.   -  person AJG85    schedule 16.06.2012
comment
ЕСТЬ ли конкретная причина, по которой вам нужен макрос? Было бы лучше написать operator<< для класса Str.   -  person Martin York    schedule 16.06.2012


Ответы (3)


Есть ли причина, по которой вы хотите сделать это как макрос?

Вы должны написать функцию для выполнения этого действия вместо использования препроцессора.


В зависимости от ваших целей есть несколько вариантов. библиотека ускоренного форматирования предоставляет отличный набор инструментов для создания форматированная строка. Вы всегда можете перегрузить operator<<, чтобы обеспечить чистый вывод, а также .

Если вы делаете это на чистом C, работает семейство методов sprintf. для создания форматированного вывода.

person Reed Copsey    schedule 16.06.2012
comment
Это на самом деле не отвечает на вопрос. - person Luchian Grigore; 16.06.2012
comment
@LuchianGrigore, для этого может потребоваться немного кода, но, в конце концов, это тот же синтаксис (или лучше) для рабочего вывода или строки. - person chris; 16.06.2012
comment
@LuchianGrigore Я пытался добавить полезную информацию для вариантов, но, думаю, моя проблема в том, что я чувствую, что прямой ответ на вопрос продвигает что-то, что в целом является плохой практикой. - person Reed Copsey; 16.06.2012
comment
Я не хочу писать для этого функцию, потому что тогда мне пришлось бы динамически выделять память или передавать буфер функции для хранения строки. Я просто подумал, что можно расширить структуру в строку с помощью макроса, я ошибаюсь? - person FearLeslie; 16.06.2012
comment
@FearLeslie Даже с макросом вы должны создать буфер какой-либо формы для хранения строковых данных, даже если они находятся в стеке. Чем это отличается от передачи буфера, выделенного стеком? - person Reed Copsey; 16.06.2012
comment
@FearLeslie Не бойтесь без необходимости :-) - person Jagannath; 16.06.2012
comment
@Reed Copsey: может быть, ты прав. Тем не менее, из любопытства, как можно написать такой макрос? - person FearLeslie; 16.06.2012
comment
@FearLeslie Макрос будет просто строить строку, поэтому любой из методов, которые вы будете использовать для этого в функции, должен быть расширен в макрос. - person Reed Copsey; 16.06.2012

Это довольно грубо и работает только на gcc/g++.

#define STRINGIFY_STR(x) \
    std::string(({ std::ostringstream ss; \
                   ss << "[a: " << x.a \
                      << ", f: " << x.f \
                      << ", c: " << x.c << "]"; \
                   ss.str(); })).c_str()

Вы должны создать строку из значений. Пожалуйста, не делай этого так. Пожалуйста, следуйте совету Рида.

Вот как я бы изменил ваш struct, чтобы его можно было красиво распечатать:

struct Str
{
    int a;
    float f;
    char *c;

    std::ostream & dump (std::ostream &os) const {
        return os << "[a: " << a
                  << ", f: " << f
                  << ", c: " << c << "]";
    }
};

std::ostream & operator << (std::ostream &os, const Str &s) {
    return s.dump(os);
}

Str s = {123, 456.789f, "AString"};

Теперь, чтобы распечатать s, вы можете использовать std::cout:

std::cout << s << std::endl;

Или, если вам действительно нужна строка:

std::stringstream ss;
s.dump(ss);
puts(ss.str().c_str());
person jxh    schedule 16.06.2012
comment
Спасибо за ответ. Да, выглядит некрасиво. Может быть, было бы лучше написать функцию-член. - person FearLeslie; 16.06.2012

Я тоже против подхода, но чтобы ответить на вопрос:

#define STRINGIFY_STR(x) \
   (std::string("[a: ") + std::to_string((long double)x.a) \
  + std::string(", f:") + std::to_string((long double)x.f) \
  + std::string(",c: ") + x.c + std::string("]") ).c_str()

Я предлагаю написать функцию-член, которая делает это.

person Luchian Grigore    schedule 16.06.2012