Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Chapter 34. Boost.StaticAssert

Boost , The Boost C++ Libraries BoostBook Documentation Subset , Part I. The Boost C++ Libraries (BoostBook Subset)

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

Chapter 34. Boost.StaticAssert

John Maddock

Steve Cleary

Распространяется под лицензией Boost Software License, версия 1.0. (См. сопроводительный файл LICENSE_1_0.txt или копию по адресуhttp://www.boost.org/LICENSE_1_0.txt)

Данное руководство также доступно вдружественном к принтеру формате PDF.

Overview and Tutorial

Заголовок<<boost/static_assert.hpp>>содержит два макроса:

BOOST_STATIC_ASSERT(x)
BOOST_STATIC_ASSERT_MSG(x, msg)

Оба создают сообщение об ошибке компиляции времени, если интегрально-постоянное выражение<x>не соответствует действительности. Другими словами, они являются компиляционным временным эквивалентом макроса утверждения; это иногда известно как «утверждение о времени компиля», но будет называться «статическим утверждением» во всех этих документах. Обратите внимание, что если условие<true>, то макросы не будут генерировать ни код, ни данные - и макросы также могут использоваться в любом пространстве имен, классе или области функций. При использовании в шаблоне статическое утверждение будет оцениваться в момент создания шаблона; это особенно полезно для проверки параметров шаблона.

Если C++0x<static_assert>функция доступна, оба макроса будут использовать ее. Для<BOOST_STATIC_ASSERT(x)>сообщение об ошибке будет строгой версией<x>. Для<BOOST_STATIC_ASSERT_MSG(x, msg)>сообщение об ошибке будет строкой<msg>.

Если функция C++0x<static_assert>недоступна,<BOOST_STATIC_ASSERT_MSG(x, msg)>будет рассматриваться как<BOOST_STATIC_ASSERT(x)>.

Следующий материал предполагает, что функция C++0x<static_assert>недоступна.

Одна из целей<BOOST_STATIC_ASSERT>- генерировать читаемые сообщения об ошибках. Они сразу же сообщают пользователю, что библиотека используется таким образом, который не поддерживается. Хотя сообщения об ошибках, очевидно, отличаются от компилятора к компилятору, вы должны увидеть что-то вроде:

Illegal use of STATIC_ASSERTION_FAILURE<false>

Который должен хотя бы привлечь внимание!

Вы можете использовать<BOOST_STATIC_ASSERT>в любом месте, где вы можете разместить декларацию, то есть в области класса, функции или пространства имен, это иллюстрируется следующими примерами:

Use at namespace scope.

Макрос может использоваться в области пространства имен, если есть какое-то требование, которое всегда должно быть верным; как правило, это означает определенное требование платформы. Предположим, что<int>должно быть по меньшей мере 32-битным интегральным типом, а<wchar_t>— неподписанным типом. Мы можем проверить это во время составления следующим образом:

#include <climits>
#include <cwchar>
#include <limits>
#include <boost/static_assert.hpp>
namespace my_conditions {
   BOOST_STATIC_ASSERT(std::numeric_limits<int>::digits >= 32);
   BOOST_STATIC_ASSERT(WCHAR_MIN >= 0);
} // namespace my_conditions

Использование пространства имен my_conditions здесь требует некоторых комментариев. Макро<BOOST_STATIC_ASSERT>работает, генерируя объявление типаdef, и поскольку типdef должен иметь имя, макрос автоматически генерирует его, искажая имя заглушки со значением<__LINE__>. Когда<BOOST_STATIC_ASSERT>используется в любом классе или функциональной области, то каждое использование<BOOST_STATIC_ASSERT>гарантированно создает имя, уникальное для этой области (при условии, что вы используете макрос только один раз на каждой линии). Однако при использовании в заголовке в области пространства имен это пространство имен может быть продолжено над несколькими заголовками, каждый из которых может иметь свои собственные статические утверждения, и на «одинаковых» линиях, тем самым генерируя дублирующие декларации. Теоретически компилятор должен молча игнорировать повторяющиеся объявления типа DEF, однако многие не делают этого (и даже если они это делают, они имеют право выдавать предупреждения в таких случаях). Чтобы избежать потенциальных проблем, если вы используете<BOOST_STATIC_ASSERT>в заголовке и в области пространства имен, то закройте их в пространстве имен, уникальном для этого заголовка.

Use at function scope

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

#include <iterator>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
template <class RandomAccessIterator >
RandomAccessIterator foo(RandomAccessIterator from,
                         RandomAccessIterator to)
{
   // this template can only be used with
   // random access iterators...
   typedef typename std::iterator_traits<
         RandomAccessIterator >::iterator_category cat;
   BOOST_STATIC_ASSERT(
      (boost::is_convertible<
         cat,
         const std::random_access_iterator_tag&>::value));
   //
   // detail goes here...
   return from;
}

Несколько сносок приведены здесь в порядке: дополнительный набор скобок вокруг утверждения, чтобы предотвратить интерпретацию запятой внутри шаблона<is_convertible>препроцессором в качестве сепаратора макроаргумента; целевой тип для<is_convertible>является эталонным типом, поскольку некоторые компиляторы имеют проблемы с использованием<is_convertible>, когда преобразование осуществляется через конструктор, определенный пользователем (в любом случае нет никакой гарантии, что классы тегов итератора являются копируемыми).

Use at class scope

Макро обычно используется внутри классов, которые являются шаблонами. Предположим, что у нас есть класс шаблонов, который требует неподписанного интегрального типа с по меньшей мере 16 битами точности в качестве аргумента шаблона, мы можем достичь этого, используя что-то вроде этого:

#include <limits>
#include <boost/static_assert.hpp>
template <class UnsignedInt>
class myclass
{
private:
   BOOST_STATIC_ASSERT_MSG(std::numeric_limits<UnsignedInt>::is_specialized, "myclass can only be specialized for types with numeric_limits support.");
   BOOST_STATIC_ASSERT_MSG(std::numeric_limits<UnsignedInt>::digits >= 16, "Template argument UnsignedInt must have at least 16 bits precision.")
   BOOST_STATIC_ASSERT_MSG(std::numeric_limits<UnsignedInt>::is_integer, "Template argument UnsignedInt must be an integer.");
   BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<UnsignedInt>::is_signed, "Template argument UnsignedInt must not be signed.");
public:
   /* details here */
};

Use in templates

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

template <class T>
struct must_not_be_instantiated
{
   BOOST_STATIC_ASSERT(false);
};

Будет производиться ошибка компилятора с некоторыми компиляторами (например, Intel 8.1 или gcc 3.4), независимо от того, был ли когда-либо создан шаблон. Обход в подобных случаях заключается в том, чтобы заставить утверждение зависеть от шаблонного параметра:

template <class T>
struct must_not_be_instantiated
{
   // this will be triggered if this type is instantiated
   BOOST_STATIC_ASSERT(sizeof(T) == 0);
};

PrevUpHomeNext

Статья Chapter 34. Boost.StaticAssert раздела The Boost C++ Libraries BoostBook Documentation Subset Part I. The Boost C++ Libraries (BoostBook Subset) может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Part I. The Boost C++ Libraries (BoostBook Subset) ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:43:05/0.030467987060547/1