Задать вопрос
PavelK
@PavelK

Как можно передать структуру в printf, а к переменным её обращаться из шаблона?

В общем вот что примерно хочется:
typedef struct TS1 {
    int a;
    int b;
    // В структуре только переменные базовых типов
} S1;

void *s1; // О структуре мы ничего не знаем, только шаблон для вывода её.
printf("A:  %d,  B: %d",  s1);

//  printf("B:  %b.d,  A: %a.d",  s1); в идеале бы вообще иметь возможность в произвольном порядке выводить

Направьте на путь, пожалуйста, как реализовать наиболее безкостыльно?
  • Вопрос задан
  • 215 просмотров
Подписаться 1 Сложный 2 комментария
Решения вопроса 3
GavriKos
@GavriKos
Сделать свою реализацию printf/tostring/<>> у структуры.
Ответ написан
Комментировать
wataru
@wataru
Разработчик на С++, экс-олимпиадник.
Во встроенный printf вы это не добавите никак. Придется писать собственную обертку и там парсить строку формата.
Так, чтобы это работало со всеми структурами, у которых есть член int a - нужны шаблоны, да. Гуглите variadic template, но это мрак и ужас. В любом случае это будет весьма громоздкий и непонятный код.

Но раз уж у вас C++, то вы вместо printf используйте cout. Переопределите operator<< для ostream и вашей структуры и выводите через cout << *s1.

Да, тут не получится в каждом конкретном месте вызова менять формат вывода, он будет одинаков везде - но так ли вам это нужно, чтобы городить костыли с printf?
Ответ написан
Комментировать
@dima20155
you don't choose c++. It chooses you
Если вы хотите выводить элементы структуры, то пусть самурая - переопределить
operator<<
примерно так:
std::ostream operator<<(std::ostream& os, const S1& s) {
    os << "s.a: " << s.a << ", s.b: " << s.b;
}


Шаблон вам здесь не пригодится, поскольку только ваша структура содержит поля a и b.
Любой другой класс/структура содержит другие поля, а соответственно, данная шаблонная функция вызовет ошибку компиляции для них из-за отсутствия соответствующих полей.

Шаблоны полезны там, где есть общий интерфейс, например, можно написать шаблонную функцию, которая проходится по контейнеру и выводит его значения (поскольку многие STL контейнеры итерируемы и этот функционал имеет единый интерфейс)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019
Bigdata Engineer
Данная задача решается мета-программированием. Это предполагает 2 фазы компилляции. Поскольку
речь идет о языке С. У нас нет рефлексии и нет шаблонов. То я вижу только такой выход.

Вобщем 2 фазы. В первой фазе - объявить структуру TS1 в каком-то обобщенном формате.
Например в JSON.
{
  "struct" : {
    "name" : "TS1",
    "fields" : [
      { "name" : "a", "type" : "int" },
      { "name" : "b", "type" : "int" }
    ]
  }
}


И сгенерировать из этой структуры код для декларации ее в языке C и для форматной
печати через printf.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы