Возможный дубликат:
Как проверить поддержку C ++ 11?
Я пишу небольшую библиотеку, и я хотел бы использовать перечисления классов, когда их поддерживает компилятор. Я также хочу использовать другие функции C ++ 11, такие как final
а также override
ключевые слова.
До сих пор я использовал приемы, чтобы убедиться, что он скомпилирован во всех версиях GCC, но когда я загрузил свой раздел Windows, Visual Studio 2010 тоже начал жаловаться. Вот пример уловок, которые я использовал:
#if __GNUC__ == 4 && (__GNUC_MINOR__ > 7 || \
(__GNUC_MINOR__ == 7 && __GNUC_PATCHLEVEL__ > 1))
# define TATO_OVERRIDE override
# define TATO_NO_THROW nothrow
#else
# define TATO_OVERRIDE
# define TATO_NO_THROW throw()
#endif
Я знаю, что новейшая версия Visual Studio уже поддерживает пакет новых функций. То, что я хотел бы иметь, это что-то вроде набора макросов, который сообщает мне, какие функции доступны в компиляторе, который я использую.
#ifdef THIS_COMPILER_SUPPORTS_CLASS_ENUMS
...
#endif
Это существует? Есть ли библиотека, которая делает это?
Документация компилятора?
Позвольте мне уточнить. Я знаю, как найти эту информацию, моя проблема в другом месте. Я не хочу просматривать всю возможную документацию компилятора, чтобы собрать эту информацию, тем более что один и тот же компилятор может поддерживать различные функции в отношении своей версии. Это то, что я делал до сих пор, и то, что я ищу, на самом деле является способом не делать этого.
Повышение на самом деле имеет широкий спектр таких макросов имеется в наличии. Вы могли бы использовать это. В противном случае единственный способ — по существу проверить версию компилятора и использовать свои знания о функциях, поддерживаемых в этой версии, чтобы решить, доступна ли функция или нет.
По сути, что делает Boost, кроме как вручную.
Были дискуссии о наличии некоторого стандартизированного механизма тестирования возможностей, но оказалось, что это не имеет никакого смысла: если компилятор реализует стандарт, все тесты функций дадут true
, Если этого не произойдет, нет никаких оснований предполагать, что он соответствует стандарту с точки зрения функциональных испытаний!
Таким образом, использование какого-либо файла конфигурации представляется наиболее надежным подходом. Лично я бы сделал это иначе, чем явно проверял бы версии компилятора: вместо этого я бы использовал что-то, пытаясь определить, поддерживает ли компилятор определенную функцию в приемлемой степени. Конфигурация может быть запущена с точки зрения autoconf
или что-то подобное.
Что касается полученной конфигурации, я бы попытался сопоставить вещи с подходящими конструкциями, а не использовать условную компиляцию вне заголовков конфигурации. Например, я бы использовал что-то вроде этого:
#if defined(KUHL_HAS_CLASS_FINAL)
# define kuhl_class_final final
#else
# define kuhl_class_final
#endif
В частности, для перечислений классов вам может понадобиться что-то более хитрое, потому что значения перечисления будут доступны только внутри области, а значения доступны только за пределами области. Таким образом, может потребоваться придумать некоторую форму дополнительного вложения в одном случае, но не в другом.
В clang есть несколько встроенных макросов для проверки различных функций: проверять макросы
Было бы хорошо, если бы все поставщики компиляторов подобрали их (и даже больше).
«То, что я хотел бы иметь, это что-то вроде набора макросов, которые сообщают мне, какие функции доступны в компиляторе, который я использую».
В стандарте такого нет.
Практический подход к различиям компилятора заключается в том, чтобы иметь заголовок для каждой поддерживаемой вами версии компилятора и компилятора. Эти заголовки должны иметь одинаковое имя. Какой из них будет включен, зависит от пути включения, использования инструмента, который легко настроить для каждого компилятора.
Я называю эту концепцию виртуальные заголовки. Я обнаружил, что он хорошо работает для трех уровней: системной зависимости, зависимости компилятора и версии. Я думаю, что схема не масштабируется больше, но с другой стороны, это, кажется, все, что нужно.