Вопрос по c++, templates, c, struct – Использование шаблонов C ++ с структурами C для самоанализа?

1

Я делаю некоторую работу на C ++ для компании, у которой все остальное написано на C (использование C не является для меня опцией :(). У них есть ряд структур данных, которые ОЧЕНЬ похожи (то есть все они имеют поля такие как «имя», «адрес» и т. д. Но по какой-то причине не существует «общей структуры», из которой они основывали все остальное (делает что-то адское). В любом случае, мне нужно сделать систему широкий анализ этих структур, находящихся в памяти, и через все это в таблицу. Не так уж плохо, но таблица должна включать записи для всех полей всех переменных, даже если они не имеют поля (struct b может иметь поле «latency», но struct a not 't - в таблице запись для каждого экземпляра a должна иметь пустую запись для «latency».

Итак, мой вопрос: есть ли способ определить во время выполнения, имеет ли структура, переданная в функцию шаблона, определенное поле? Или мне придется написать какой-нибудь черный магический макрос, который сделает это для меня? (Проблема в том, что я не могу использовать специализацию шаблонов)

Спасибо! Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь спрашивать!

Вот фрагмент того, о чем я думал ...

struct A
{
  char name[256];
  int index;
  float percision;
};

struct B
{
  int index;
  char name[256];
  int latency;
};

/* More annoying similar structs... note that all of the above are defined in files that were compiled as C - not C++ */

struct Entry
{
  char name[256];
  int index;
  float percision;
  int latency;
  /* more fields that are specific to only 1 or more structure */
};

template<typename T> struct Entry gatherFrom( T *ptr )
{
  Entry entry;

  strcpy( entry.name, ptr->name, strlen( ptr->name ) );
  entry.index = ptr->index;
  /* Something like this perhaps? */
  entry.percision = type_contains_field( "percision" ) ? ptr->percision : -1;
}

int main()
{
  struct A a;
  struct B b;

  /* initialization.. */

  Entry e  = gatherFrom( a );
  Entry e2 = gatherFrom ( b );

  return 0;
}
Я работаю в C ++, пытаясь извлечь данные из набора C-структур. Neil
«Использование C для меня не вариант», может быть, я идеалист, но однажды мне приснилось, что программисты на C ++ действительно могут кодировать C… Macmade
В C нет способа идентифицировать тип во время выполнения. Поскольку вы упомянули «макросы черной магии», можете ли вы привести пример того, что будет делать макрос? Возможно, это может дать подсказку о том, какая информация доступна во время выполнения. Deepan
Может бытьthis это то, что вы хотите? jxh
determine at runtime а такжеtemplate function на самом деле не идут вместе ... шаблоны разрешаются во время компиляции. Вы можете, вероятно, использовать SFINAE для обнаружения вcompile time существует ли поле или нет. David Rodríguez - dribeas

Ваш Ответ

2   ответа
1

everything else written in C (using C isn't an option for me :( ).

Сначала я хотел бы процитировать то, что Линус Торвальдс сказал по этому поводу:

From: Linus Torvalds <torvalds <at> linux-foundation.org>
Subject: Re: [RFC] Convert builin-mailinfo.c to use The Better String Library.
Newsgroups: gmane.comp.version-control.git
Date: 2007-09-06 17:50:28 GMT (2 years, 14 weeks, 16 hours and 36 minutes ago)

C++ is a horrible language. It's made more horrible by the fact that a lot 
of substandard programmers use it, to the point where it's much much 
easier to generate total and utter crap with it. Quite frankly, even if 
the choice of C were to do *nothing* but keep the C++ programmers out, 
that in itself would be a huge reason to use C.

http://harmful.cat-v.org/software/c++/linus

They have a number of data structures that are VERY similar (i.e., they all have fields such as "name", "address", etc. But, for whatever reason there isn't a common structure that they used to base everything else off of (makes doing anything hell).

У них могли быть очень веские причины для этого. Поместить общие поля в единую базовую структуру (класс) может показаться отличной идеей. Но это действительно усложняет ситуацию, если вы хотите применить серьезные изменения к одной из структур (заменить некоторые поля, типы изменений и т. Д.), Оставив остальные нетронутыми. ООП, конечно, не единственный верный способ сделать что-то.

So, my question is, is there a way to determine at runtime if a structure that has been passed into a template function has a specific field?

Нет, это невозможно. Ни в C, ни в C ++, потому что вся информация о типах отбрасывается при создании двоичного файла. В C или C ++ нет ни отражения, ни самоанализа. Ну, технически отладочная информация, которую выдает компиляторdoes предоставить эту информацию, но для этого нет встроенной функции языка. Также этот вид отладочной информации основан на анализе, выполненном во время компиляции, а не во время выполнения. В C ++ есть RTTI, но это только очень грубая система, чтобы определить, к какому классу относится экземпляр. Это не помогает с членами класса или структуры.

Но почему вы все равно делаете это во время выполнения?

Anywho, I need to do a system-wide analysis of these structs that are in memory, and through it all into a table.

Вы должны быть действительно счастливы, что вы должны анализировать C, а не C ++. Потому что C действительно очень легко анализировать (в отличие от C ++, который очень сложно анализировать, в основном из-за этих чертовых шаблонов). Особенно структурирует. Я бы просто написал небольшой и простой скрипт, который извлекает все определения структуры из C-источников. Однако, поскольку структуры имеют постоянный размер, они часто содержат указатели на динамически размещаемые данные. И если вы не хотите исправлять свой распределитель, я думаю, что самый простой способ проанализировать это - подключиться к отладчику и записать использование памяти каждым уникальным объектом, указатель которого назначен члену структуры.

@datenwolf: заявленная проблема состоит не в том, чтобы обнаружить все поля структуры, а в том, каким поднабором предопределенного набора она обладает. Это возможно, используя compile-introspection. Увидетьmy answer для деталей.
@MaximYegorushkin: После моих приключений в Turbo Pascal в начале 1990-х я сначала изучил C ++ и потратил годы на его использование (около 2005 года), прежде чем я действительно научился думать и кодировать на C. И с тех пор я сильно предпочитаю программирование на C, а не написание кода. в C ++. Я думаю, что важным катализатором для этого было то, что примерно в это же время я познакомился с функциональным программированием, которое стало своего рода откровением о том, насколько странным и запутанным является C ++. Черт, я даже потратил впустую некоторое время, пытаясь реализовать шаблонизирующий синтаксический анализатор C ++, похожий на Qt.moc, Я прошел детоксикацию C ++ и постарался избежать этого.
@MaximYegorushkin: Мой аргумент в том, что C ++ стал настолько запутанным, что фактически запрещает эффективное повторное использование кода. Для любого данного проекта будет выбрано общее подмножество языковых функций и используемых идиом. Как только вы попытаетесь объединить это с другим проектом C ++, все начнётся. В 1998 году я написал действительно хороший фреймворк для терминальных интерактивных приложений. Подумайте Qt - но для консоли. Все было сделано в C ++; Теперь я глубоко сожалею о написании этого на C ++, потому что вряд ли смогу использовать его в новых проектах.
@MSalters: Ага, отсутствие знаний C ++. Просветите меня. К вашему сведению: C ++ статически компилируется. C ++ не имеет встроенного отражения. C ++ не имеет встроенного самоанализа (отражение было запланированной особенностью C ++ 0x, которая, однако, была удалена). Теперь скажите мне: без размышлений или самоанализа, как вы определяетеruntime какие члены структуры / класса есть в объекте?
Я полностью согласен с точкой зрения C против C ++ - я ненавижу C ++, но это то, что мне сказали использовать, поэтому я решил, что попытаюсь воспользоваться преимуществами шаблонов. Итак, могу ли я проверить во время компиляции или на этапе препроцессора, чтобы увидеть, был ли вызов недействительным, и если это так, выбрать другой маршрут? (Похоже на #ifdef)? Я думаю, что это было бы оптимальным - и я думаю, что это тоже то, чем занимается SFINAE, но это не является частью стандарта, верно? Neil
1

Да, это совсем не сложно. Просто положите обаA иEntry в одном объекте, и сделатьEntry гражданин второго сорта:

void setDefaultValues(Entry*); // You should be able to provide these.
struct Entry {
  int x;
  int y;
};
struct Indirect : public Entry { };
template<typename T> struct EntryOr : public T, Indirect
{
  setDefaultValues(this);
};

// From C code
struct A {
  int x;
}

int main()
{
  EntryOr<A> foo;
  foo.x = 5; // A::x
  std::cout << foo.x << foo.y; // Prints A::x and Entry::y
}

(Ссылка на сайт)

У меня нет времени поиграть с ним прямо сейчас, но это действительно интересно. Я буду возиться с этим позже сегодня вечером или в эти выходные. Neil
Мы говорим о C ++? Если так: ошибка C2385: неоднозначный доступ к 'x', класс не может наследоваться от более чем одной базы

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