Расширение макроса C / C ++ против генерации кода - PullRequest
6 голосов
/ 27 ноября 2009

Как расширение макросов, так и генерация кода имеют свои плюсы и минусы. Какой твой любимый подход и почему? Когда мы должны выбрать один над другим? Пожалуйста, советуйте. Спасибо!

Расширение макроса может быть очень удобным и полезным: http://dtemplatelib.sourceforge.net/table.htm

против

Хотя генерация кода дает вам много приятного кода: http://code.google.com/p/protobuf/ http://incubator.apache.org/thrift/

Ответы [ 4 ]

9 голосов
/ 27 ноября 2009

Для c ++ я предпочитаю либо метапрограммирование шаблонов, либо генерацию кода, а не макросы, но макросы по-прежнему имеют свое применение.

Пример, который вы привели с dbtemplatelib, может быть покрыт c ++ 0x Вариативными шаблонами , с дополнительными преимуществами, такими как проверка типов и т. Д.

5 голосов
/ 27 ноября 2009

В C или C ++ расширение макросов общеизвестно сложно отлаживать. С другой стороны, написание генератора кода легче отлаживать, потому что это отдельная программа сама по себе.

Однако вы должны знать, что это всего лишь ограничение препроцессора Си. Например, в семействе языков Lisp расширение макроса - это генерация кода , это одно и то же. Чтобы написать макрос, вы пишете программу (на Лиспе) для преобразования ввода S-выражения в другое S-выражение, которое затем передается компилятору.

3 голосов
/ 30 ноября 2009

У обоих есть свои проблемы. В отличие от макросов, генерация кода может создавать читаемый и отлаживаемый (это даже слово?) Код, но он менее гибок и труднее изменить.

2 голосов
/ 30 ноября 2009

Это компромисс. Позвольте мне привести пример. Я наткнулся на технику дифференциального исполнения примерно в 1985 году и считаю, что это действительно хороший инструмент для программирования пользовательских интерфейсов. По сути, это простые структурированные программы, такие как:

void Foo(..args..){
  x = y;
  if (..some test..){
    Bar(arg1, ...)
  }
  while(..another test..){
    ...
  }
  ...
}

и гадости с такой структурой управления:

void deFoo(..args..){
  if (mode & 1){x = y;}
  {int svmode = mode; if (deIf(..some test..)){
    deBar(((mode & 1) arg1 : 0), ...)
  } mode = svmode;}
  {int svmode = mode; while(deIf(..another test..)){
    ...
  } mode = svmode;}
  ...
}

Теперь действительно хороший способ сделать это - написать синтаксический анализатор для C или любого другого базового языка, а затем пройтись по дереву синтаксического анализа, генерируя нужный мне код. (Когда я делал это в Лиспе, эта часть была легкой.)

Но кто хочет написать парсер для C, C ++ или чего-то еще?

Вместо этого я просто пишу макросы, чтобы можно было написать код следующим образом:

void deFoo(..args..){
  PROTECT(x = y);
  IF(..some test..)
    deBar(PROTECT(arg1), ...)
  END
  WHILE(..another test..)
    ...
  END
  ...
}

Однако, когда я делаю это в C #, кто-то в своей мудрости решил, что макросы плохие, и я не хочу писать синтаксический анализатор C #, поэтому я должен выполнить генерацию кода вручную. Это королевская боль, но она все же стоит того, чтобы кодировать эти вещи.

...