Мы знаем, что такая библиотека будет вечной работой. И как таковые мы ожидаем, и с нетерпением ждем, что другие внесут исправления и дополнения в предефы. Имея это в виду, мы должны придерживаться последовательного способа определения новых предефов. Следовательно, все текущие и будущие предефы следуют одной и той же структуре и требованиям.
Все предефы должны следовать набору требований:
- Заголовки должны использовать Лицензию программного обеспечения Boost.
- Предисловие по умолчанию должно быть определено как<
BOOST_VERSION_NUMBER_NOT_AVAILABLE
>.
- Предеф должен быть переопределен до ненулевого значения после обнаружения.
- Предисловие по умолчанию должно быть определено до<
BOOST_VERSION_NUMBER_AVAILABLE
>, когда предисловие обнаружено.
- По возможности, предисловие будет определяться как номер версии.
- Предисловие должно определять<
*_AVAILABLE
>макросы по мере необходимости.
- Предеф должен определять символическое постоянное имя строки макрос.
- Предеф должен заявить о себе после определения для системы тестирования.
- Предеф должен гарантировать, что он является единственным, определенным как обнаруженный для каждой категории.
- Но предеф может определить<
*_EMULATED
>макроса, чтобы указать, что он был ранее обнаружен другим заголовком и «эмулируется» системой. Обратите внимание, что макросы<*_AVAILABLE
>все еще должны быть определены в этой ситуации.
И есть некоторые дополнительные рекомендации, которым должны следовать заголовки predef:
- Обнаружение должно избегать включения дополнительных заголовков, которые в противном случае не могли бы быть включены по умолчанию.
- Если обнаружение должно включать в себя заголовок, предпочтите охранять его в пределах обнаружения, если это возможно.
- Если обнаружение должно включать заголовки безоговорочно и имеет выбор заголовков для включения, предпочтите те, которые имеют наименьшее влияние. Т.е. включить ту, которая имеет минимальный набор определений и других зависимостей.
Для общей согласованности предлагается, чтобы новые заголовки предифа следовали структуре ниже, как это делают текущие заголовки предифа. Во-первых, у нас есть заявление об авторских правах и лицензии, за которым следует охрана:
#ifndef BOOST_PREDEF_category_tag_H
#define BOOST_PREDEF_category_tag_H
Если обнаружение зависит от обнаружения другого предефа, вы должны включить эти заголовки здесь.
#include <boost/predef/CATEGORY_TAG/DEPENDENCY.h>
В зависимости от того, как вы определяете предеф, вы должны, как минимум, включить заголовок<version_number.h
>. Но вы также можете включить заголовок<make.h
>для номера версии, разлагающего служебные макросы:
#include <boost/predef/version_number.h>
#include <boost/predef/make.h>
Библиотека Predef использует Quickbook для документации и для отдельных предефов, чтобы появиться в справочном разделе, мы добавляем документацию в коде, за которой следует определение макроса предефа с нулевым значением по умолчанию. Мы настоятельно рекомендуем это конкретное размещение документации и определение по умолчанию, потому что некоторые среды разработки автоматически интерпретируют это и предоставляют встроенную помощь для макроса. В частности, это работает для популярной Eclipse IDE:
#define BOOST_category_tag BOOST_VERSION_NUMBER_NOT_AVAILABLE
Далее следует выявление и определение конкретного предефа. Структура для этого состоит в том, чтобы сделать единую общую проверку<condition_a
>и разместить дальнейшее обнаружение версии внутри этого. Первым действием в общей проверке является «<#undef
BOOST_category_tag
>», которое не определяет нулевое значение по умолчанию. Остальное зависит от того, как сделать проверку для определения версии. Но, как минимум, это должно быть «<#define
BOOST_category_tagBOOST_VERSION_NUMBER_AVAILABLE
>» в качестве запасного варианта, чтобы минимально указать, что был обнаружен предеф:
#if (condition_a)
# undef BOOST_category_tag
# if (condition_b)
# define BOOST_category_tag BOOST_VERSION_NUMBER(major,minor,patch)
# else
# define BOOST_category_tag BOOST_VERSION_NUMBER_AVAILABLE
# endif
#endif
Мы также должны предоставить<*_AVAILABLE
>версии предисловия.
#if BOOST_category_tag
# define BOOST_category_tag_AVAILABLE
#endif
Для удобства мы также хотим предоставить<*_NAME
>макрос:
#define BOOST_catagory_tag_NAME "Name"
Тестирование макросов predef автоматизировано для создания проверок для всех определенных предефов, обнаруженных или нет. Для этого нужно объявить предеф в тест-систему. Эта декларация пуста для регулярного использования. А во время тестовых программ они расширяются специально для создания информационного выхода:
#include <boost/predef/detail/test.h>
BOOST_PREDEF_DECLARE_TEST(BOOST_category_tag,BOOST_category_tag_NAME)
И, конечно, в последний раз нужно закрыть охрану:
#endif
Для заголовков предефов, которые должны быть взаимоисключающими при обнаружении, нам нужно добавить чеки и определения для обнаружения, когда предеф обнаруживается несколькими заголовками.
Внутренний компилятор, операционная система и платформы определяют<BOOST_PREDEF_DETAIL_COMP_DETECTED
>,<BOOST_PREDEF_DEFAIL_OS_DETECTED
>и<BOOST_PREDEF_DETAIL_PLAT_DETECTED
>соответственно при первом обнаружении предефа. Это используется для защиты от множественного определения обнаружения в более поздних включенных заголовках. В этих случаях обнаружение будет записываться как:
#if !BOOST_PREDEF_DETAIL_category_DETECTED && (condition_a)
# undef BOOST_category_tag
# if (condition_b)
# define BOOST_category_tag BOOST_VERSION_NUMBER(major,minor,patch)
# else
# define BOOST_category_tag BOOST_VERSION_NUMBER(0,0,1)
# endif
#endif
И мы также включаем заголовок, который определяет макрос<*_DETECTED
>, когда у нас есть обнаружение:
#if BOOST_category_tag
# define BOOST_category_tag_AVAILABLE
# include <boost/predef/detail/CATEGORY_detected.h>
#endif
Все остальное в заголовке совпадает с основным заголовком обнаружения.
Поскольку компиляторы часто эмулируются другими компиляторами, мы оба хотим иметь исключительное обнаружение компилятора, а также предоставить информацию о том, что мы обнаружили эмуляцию компилятора. Для этого мы определяем локальный<*_DETECTION
>макрос для обнаружения компилятора. И условно определяют либо базовый компилятор predef<BOOST_COMP_compiler
>, либо альтернативный<BOOST_COMP_compiler_EMULATED
>predef.
Первоначальное обнаружение будет выглядеть так:
#if (condition_a)
# if (condition_b)
# define BOOST_COMP_tag_DETECTION BOOST_VERSION_NUMBER(major,minor,patch)
# else
# define BOOST_COMP_tag_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
# endif
#endif
И тогда мы можем условно определить основание или эмулированные предефы:
#ifdef BOOST_COMP_tag_DETECTION
# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
# define BOOST_COMP_tag_EMULATED BOOST_COMP_tag_DETECTION
# else
# undef BOOST_COMP_tag
# define BOOST_COMP_tag BOOST_COMP_tag_DETECTION
# endif
# define BOOST_category_tag_AVAILABLE
# include <boost/predef/detail/comp_detected.h>
#endif
В том числе:
#include <boost/predef/make.h>
Один получит набор полезных макросов для разложения общих макросов версий, определенных компиляторами. Например, компилятор EDG использует простой 3-значный макрос версии (M,N,P). Его можно разложить и определить как:
#define BOOST_CCOMP_EDG BOOST_PREDEF_MAKE_N_N_N(__EDG_VERSION__)
Макросы разложения делятся на три типа: десятичное разложение, шестидесятичное разложение и декомпозиция даты. Они следуют формату использования «N» для десятичных, «F» для шестнадцатеричных и «Y», «M», «D» для дат.