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

(Генерирование встроенных сообщений)

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

Формат:

BOOST_MPL_ASSERT_MSG(condition, message, types);

Этот макрос подходит как для отображения интегральных константных выражений, так и типов парметров функции.

BOOST_MPL_ASSERT_MSG(N::value >= 0, FACTORIAL_of_NEGATIVE_NUMBER, (N));

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

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

****************(factorial<mpl_::int_<-5>

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

(mpl_::int_<-5>)' to non-scalar type 'mpl_::assert<false>'

requested.

Список параметров «(N)», мог бы быть пустым «()»:

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

****************(factorial<mpl_::int_<-5>

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

()' to non-scalar type 'mpl_::assert<false>'

requested.

BOOST_MPL_ASSERT_MSG требует некоторой осторожности, так как типы аргументов, используется в списке параметров функции, а также некоторые типы мы могли бы иметь особое значение в этом контексте. Например, пустой параметр (void) будет исключен из диагностики, так как int F (void) - это int F (). Кроме того, тип пустого параметра (void) может быть использован только один раз в спсике параметров функции: int F (void,void) – недопустимый синтаксис. Кроме того, массив и тип функции интерпретируются как указатель и указатель на функцию, соответственно:

int f(int x[2], char* (long))

что эквивалентно:

int f(int *x, char* (*)(long))

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

BOOST_MPL_ASSERT_MSG(condition, message, (types<types >));

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

BOOST_MPL_ASSERT_MSG

(

boost::is_class<N>::value,

NOT_an_INTEGRAL_CONSTANT_WRAPPER,

(types<N>)

);

При передаче, например, типа «void», диагностика будет следующей (MSVC7.1):

foo.cpp(34) : error C2664: 'mpl_::assertion_failed' : cannot

convert parameter 1 from 'mpl_::failed

****************(__thiscall

factorial<N>::NOT_an_INTEGRAL_CONSTANT_WRAPPER::*

*************** )(mpl_::assert_::types<T1>)

' to 'mpl_::assert<false>::type'

with

[

N=void,

T1=void

]

Распознавание до 4 типов аргументов более корректно работает в тех компиляторах, где диагностика не отображает шаблонные параметры по умолчанию. В противном случае, сообщение может иметь следующий вид (Intel C++ 8.0 учитывает шаблонные параметры по умолчанию):

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

"mpl_::assertion_failed" matches the argument list

argument types are: (mpl_::failed ****************

(factorial<void>::NOT_an_INTEGRAL_CONSTANT_WRAPPER::

****************)(mpl_::assert_::types<void, mpl_::na,

mpl_::na, mpl_::na>))

BOOST_MPL_ASSERT_MSG(

^

detected during instantiation of class "factorial<N>

[with N=void]" at line 37

В то время как настроенные предикаты, используемые в BOOST_MPL_ASSERT должны быть расположены в пространстве имен макроса, то сообщения генерируемые из BOOST_MPL_ASSERT_MSG выступает как квалифицированные элементы той области видимости, где утверждение было выдано (в данном случае факториал <void>). Потому, компиляторы которые поддерживают чтение глубоких переопределений посредством typedef, способны делать вставки типов нечитаемых расширений в диагностику.

Например, при инстанцировании:

mpl::transform<mpl::vector<void>, factorial<mpl::_>>

Диагнотика (Intel C++ 8.0):

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

"mpl_::assertion_failed" matches the argument list

argument types are: (mpl_::failed

****************(factorial<boost::mpl::bind1<

boost::mpl::quote1<factorial, boost::mpl::void_>,

boost::mpl::lambda<mpl_::_,

boost::mpl::void_>::result_>::apply<

boost::mpl::bind1<factorial<mpl_::_>,

mpl_::_2>::apply<boost::mpl::aux::fold_impl<1,

boost::mpl::begin<boost::mpl::vector<void, mpl_::na,

mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,

mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,

mpl_::na, mpl_::na, mpl_::na,

...four similar long lines omitted...

mpl_::na>::t1>::NOT_an_INTEGRAL_CONSTANT_WRAPPER::

****************)(mpl_::assert_::types<boost::mpl::bind1<

line continued...

...five similar lines omitted...

BOOST_MPL_ASSERT_MSG(

^

Вывод такой информации явно снижает читабельность диагностики.

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