Есть ли способ создать макрос препроцессора для функции? - PullRequest
2 голосов
/ 23 марта 2012

Можно ли создать макрос препроцессора C ++ на основе результата функции?

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

#define SCREEN_HEIGHT   GetSystemMetrics(SM_CYVIRTUALSCREEN)

Затем я хочу использовать результат для установки значений на основе высоты экрана:

#if SCREEN_HEIGHT < 1200
    #define TOP_COORD     200
    #define BOTTOM_COORD  500
    #define LEFT_COORD    0
    #define RIGHT_COORD   1280
#else
    #define TOP_COORD     1100
    #define BOTTOM_COORD  1400
    #define LEFT_COORD    0
    #define RIGHT_COORD   1280
#endif

Это не работает, так как SCREEN_HEIGHT, похоже, не определяется должным образом.

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

Ответы [ 4 ]

5 голосов
/ 23 марта 2012

Нет.Макросы полностью оцениваются во время компиляции, концептуально, по крайней мере, препроцессором, прежде чем фактический код будет даже скомпилирован, а выражения в #if и т. Д. Должны быть выражениями препроцессора.Высота экрана не может быть известна, пока не запустится программа.

2 голосов
/ 23 марта 2012

Реальные функции обычно вызываются только во время выполнения. Даже подобные функции, такие как sizeof обобщенные константные выражения - благодаря @Pubby за это замечание) оцениваются компилятором после этапа предварительной обработки. К этому времени все содержимое препроцессора было заменено в коде - компилятор понятия не имеет о таких вещах, как #if. Поэтому то, что вы хотите, невозможно с помощью макросов.

Однако с шаблонами это возможно. Если подумать, не в этом случае, поскольку фактическая высота экрана не может быть известна до времени выполнения.

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

2 голосов
/ 23 марта 2012

Нет, это не может быть сделано.Как вы ожидаете сделать решение времени компиляции, которое зависит от свойства экрана, на котором будет запускаться приложение?Вы не можете знать это во время компиляции.

0 голосов
/ 23 марта 2012

Если GetSystemMetrics будет макросом, то вы можете сделать это.Если GetSystemMetrics будет constexpr, то вы можете использовать черты.

Но поскольку GetSystemMetrics - нормальная функция, вам придется работать с обычным C ++.

struct system_metrics_ {
  int top, bottom, left, right;

  system_metrics_()
  {
    if (GetSystemMetrics(SM_CYVIRTUALSCREEN) < 1200) { /* first case */ }
    else { /* second case */ }
  }
};

// define this method outside the header
const system_metrics_& system_metrics() { static system_metrics_ sm; return sm; }

// legacy code
#define TOP_COORD     (system_metrics().top)
#define BOTTOM_COORD  (system_metrics().bottom)
#define LEFT_COORD    (system_metrics().left)
#define RIGHT_COORD   (system_metrics().right)
...