Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
template_metaprogramming_ru.docx
Скачиваний:
12
Добавлен:
01.07.2025
Размер:
774 Кб
Скачать
☆

Формат:

BOOST_MPL_ASSERT_RELATION(

integral-constant, comparison-operator, integral-constant);

для применения к примеру с факториалом, необходимо запистать так:

BOOST_MPL_ASSERT_RELATION(N::value, >=, 0);

Сообщение (GCC):

...

foo.cpp:30: error: conversion from

'mpl_::failed************mpl_::assert_relation<greater_equal, -5,

0>::************' to non-scalar type 'mpl_::assert<false>'

requested

...

Сообщение (Intel):

foo.cpp(30): error: no instance of function template

"mpl_::assertion_failed" matches the argument list

argument types are: (mpl_::failed

************mpl_::assert_relation< mpl_::operator>=, -5L, 0L

>::************)

BOOST_MPL_ASSERT_RELATION(N::value, >=, 0);

^

detected during instantiation of class "factorial<N>

[with N=mpl_::int_<-5>]" at line 33

Индивидуальные сообщения утверждений

Утверждение макросов прекрасно подходят для внутренней проверки библиотеки, но они не всегда генерируют сообщения в наиболее подходящей форме для пользователей библиотеки.

Метафункция факториала не лучшим образом иллюстрируют тот факт, что аргумент должен быть неотрицательным, сообщая о невыполнении условия N>= 0 не удалось.

Часто утверждения отображают низкоуровневые детали реализации, а не самой абстракции, с которой работает пользователь. Например проверка соответствия типов в конструкторе преобразования:

// Конструктор преобразования:

template <class OtherDimensions>

quantity(quantity<T, OtherDimensions> const& rhs) : m_value(rhs.value())

{

BOOST_STATIC_ASSERT

((

// проверка идентичности размерностей:

mpl::equal<Dimensions, OtherDimensions>::type::value

));

}

Если утверждение не выполняется, то пользователь получить следующую информацию, примерно в таком порядке:

  • Несоответствие типов проверямых абстракций (метрик, в примере из метрического анализа);

  • Тип первой абстракции, которому не соответсвует переданная в качестве аргумента (первая метрика и ее показатели степеней).

Но, ни одна из этой информации, непосредственно, не представлена в диагностике.

Получив больший контроль над содержанием сообщений, можно было бы их организовтаь так как необходимо.

Настройка предиката:

Чтобы вывести специальное сообщение, можно воспользоваться тем, что BOOST_MPL_ASSERT выводит имя своего предиката в диагностике. Так, все, что может быть представлено как класс, может быть выведено в диагностике:

// specializations are nullary metafunctions that compute n>0

template <int n>

struct FACTORIAL_of_NEGATIVE_NUMBER

: mpl::greater_equal<mpl::int_<n>, mpl::int_<0> >

{};

template <class N>

struct factorial

: mpl::eval_if<

mpl::equal_to<N, mpl::int_<0>>,

mpl::int_<1>,

mpl::multiplies<

N,

factorial<typename mpl::prior<N>::type>

>

>

{

BOOST_MPL_ASSERT((FACTORIAL_of_NEGATIVE_NUMBER<N::value>));

};

Диагностика (GCC):

foo.cpp:30: error: conversion from 'mpl_::failed

************FACTORIAL_of_NEGATIVE_NUMBER<-5>::************' to

non-scalar type 'mpl_::assert<false>' requested

Проблема такого подхода в том, что он требует прерывания потока кода, чтобы написать предикат в области пространства имен, только с целью вывести сообщение об ошибке. А некоторые компиляторы либо не будут это отображать вообще (MSVC10), либо (Intel C ++) будет отображать строку, содержащую утверждение:

foo.cpp(30): error: no instance of function template

"mpl_::assertion_failed" matches the argument list

argument types are: (mpl_::failed

************FACTORIAL_of_NEGATIVE_NUMBER<-5>::************)

BOOST_MPL_ASSERT((FACTORIAL_of_NEGATIVE_NUMBER<N::value>));

^

Но, если сделать текст сообщения более однозначным, то путаницы можно избежать:

template <int n>

struct FACTORIAL_requires_NONNEGATIVE_argument

: mpl::greater_equal<mpl::int_<n>, mpl::int_<0>>

{};

//...

BOOST_MPL_ASSERT

((

FACTORIAL_requires_NONNEGATIVE_argument<N::value>

));

BOOST_MPL_ASSERT_MSG

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]