Строгое соответствие стандартам с Visual Stack Overflow

Этот вопрос не совпадает с одним из них:

Я использую Windows 7 и Visual Studio Express 2012, но не ожидаю, что ни один из них не повлияет на ответ на этот вопрос.

tl; dr. Как мне лучше всего противодействовать / предотвращать / терпеть последствия следующего отрывка из math.h, в то же время позволяя компилировать его с Visual C ++?

#if     !__STDC__

/* Non-ANSI names for compatibility */

#define DOMAIN      _DOMAIN
#define SING        _SING
#define OVERFLOW    _OVERFLOW
#define UNDERFLOW   _UNDERFLOW
#define TLOSS       _TLOSS
#define PLOSS       _PLOSS

#define matherr     _matherr

Предыстория: я пишу увлекательный текстовый проект C ++, общие цели которого выходят далеко за рамки этого вопроса. Я использую GNU Make (для удобства и переносимости), чтобы скомпилировать его с Cygwin g ++ и cl.exe, и предполагаю, что среда строго соответствует стандартам … пока что. Я начинаю думать, что Windows просто не допускает такого предположения.

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

Заголовочные файлы GCC, Visual C ++ и Mac OS X (независимо от llvm-gcc) все определяют OVERFLOW а также UNDERFLOWсреди других нестандартных макросов в math.h по умолчанию.

  • GCC имеет выбор документированных средств чистого предотвращения этих определений.
  • Mac OS X имеет несколько недокументированных способов сделать то же самое, одно из которых (_POSIX_C_SOURCE) совпадает с документацией GCC. (Я упоминаю об этом в интересах компенсации отсутствия документации Apple; у меня есть история с этими идентификаторами.)
  • MSDN документы параметр командной строки / u в качестве средства (через __STDC__ макро) предотвращения определения немного нестандартные макросы в Visual C ++. Как показано в начале этого вопроса, __STDC__ макрос также мешает определению OVERFLOW а также UNDERFLOW,

Обнаружив, что ключ / u будет препятствовать определениям, которые меня интересуют, я добавил его в свой make-файл. Но потом я получил новую ошибку из строки 44 файла crtdefs.h:

error C1189: Only Win32 target supported!

Это потому что _WIN32 больше не определяется. Немного поиска показало, что crtdefs.h связан с Windows Driver Development Kit. Я не занимаюсь разработкой драйвера; могу ли я как-то не использовать этот заголовок? Или мне просто нужно переименовать мои члены enum, чтобы терпеть нестандартное поведение Windows?

1

Решение

Вместо использования /u переключатель компилятора, который имеет несколько эффектов, просто используйте /D__STDC__=1 что вызывает __STDC__ макрос, который будет определен, и ничего больше.

1

Другие решения

На ум приходят две возможности.

Во-первых, убедитесь, что вы меняете конкретные эффекты, когда вы включаете math.hс чем-то вроде:

#include <math.h>
#undef OVERFLOW
#undef UNDERFLOW

Теперь, это может также вызвать проблемы где-нибудь с кодом, который ожидает, что эти вещи будут определены правильно. Однако даже в этом случае вы можете изменить свое программное обеспечение, чтобы использовать другое имя для math.h из них:

#include <math.h>
#undef OVERFLOW
#undef UNDERFLOW
#define MATH_H_OVERFLOW  _OVERFLOW
#define MATH_H_UNDERFLOW _UNDERFLOW

Вам просто нужно убедиться, что весь исходный код (уже скомпилированный код, такой как библиотеки) не имеет значения), который хочет использовать math.h те, использования MATH_H_* константы вместо тех, что в вашем перечислении.


Во-вторых, нужно очень тщательно подумать о том, сколько усилий вы вкладываете в этот квест, по сравнению с количеством усилий, которое потребуется для простого переименования вашего квеста. enum члены к чему-то, что не конфликт. Что-то вроде использования Overflow для вашего перечисления (вместо OVERFLOW) будет моей первой попыткой, поскольку в обоих случаях все равно остается одинаковое количество информации, и это устраняет непосредственный конфликт.

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

1

В C ++ 11 вы можете использовать объемные перечисления:

enum class Flows { Underflow, Overflow };

Теперь вы ссылаетесь на Flows :: Underflow и Flows :: Overflow.

Даже в C ++ 98 рекомендуется использовать симуляцию с классами:

class Flows
{
public:
enum Value { Underflow, Overflow };
};
0