Как я помню, BOOST_MPL_ASSERT
был когда-то предпочтительным. Это все еще так? Кто-нибудь знает, почему?
Что лучше BOOST_MPL_ASSERT или BOOST_STATIC_ASSERT?
Ответ 1
[Отвечая на мой собственный вопрос]
Это зависит. Это сравнение яблок с апельсинами. Хотя подобные макросы НЕ взаимозаменяемы. Вот краткое описание того, как каждый работает:
BOOST_STATIC_ASSERT( P )
генерирует ошибку компиляции, если P != true
.
BOOST_MPL_ASSERT(( P ))
генерирует ошибку компиляции, если P::type::value != true
.
Последняя форма, несмотря на требование двойных круглых скобок, особенно полезна, поскольку она может генерировать более информативные сообщения об ошибках, если в качестве предикатов использовать Boolean nullary Metafunctions из Boost.MPL или TR1 <type_traits>
.
Вот пример программы, демонстрирующей, как использовать (и неправильно использовать) эти макросы:
#include <boost/static_assert.hpp>
#include <boost/mpl/assert.hpp>
#include <type_traits>
using namespace ::boost::mpl;
using namespace ::std::tr1;
struct A {};
struct Z {};
int main() {
// boolean predicates
BOOST_STATIC_ASSERT( true ); // OK
BOOST_STATIC_ASSERT( false ); // assert
// BOOST_MPL_ASSERT( false ); // syntax error!
// BOOST_MPL_ASSERT(( false )); // syntax error!
BOOST_MPL_ASSERT(( bool_< true > )); // OK
BOOST_MPL_ASSERT(( bool_< false > )); // assert
// metafunction predicates
BOOST_STATIC_ASSERT(( is_same< A, A >::type::value ));// OK
BOOST_STATIC_ASSERT(( is_same< A, Z >::type::value ));// assert, line 19
BOOST_MPL_ASSERT(( is_same< A, A > )); // OK
BOOST_MPL_ASSERT(( is_same< A, Z > )); // assert, line 21
return 0;
}
Для сравнения приведены сообщения об ошибках моего компилятора (Microsoft Visual С++ 2008), сгенерированного для строк 19 и 21 выше:
1>static_assert.cpp(19) : error C2027: use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'
1> with
1> [
1> x=false
1> ]
1>static_assert.cpp(21) : error C2664: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from 'boost::mpl::failed ************std::tr1::is_same<_Ty1,_Ty2>::* ***********' to 'boost::mpl::assert<false>::type'
1> with
1> [
1> _Ty1=A,
1> _Ty2=Z
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
Итак, если вы используете метафайлы (как определено здесь) в качестве предикатов, тогда BOOST_MPL_ASSERT
является менее подробным для кода и более информативным, когда он утверждает.
Для простых булевых предикатов BOOST_STATIC_ASSERT
менее подробный для кода, хотя его сообщения об ошибках могут быть менее ясными (в зависимости от вашего компилятора).
Ответ 2
BOOST_MPL_ASSERT
(все еще) обычно считается лучше. Сообщения от него несколько легче увидеть (и понять, если вы используете BOOST_MPL_ASSERT_MSG
). Несколько месяцев назад были разговоры об обесценивании BOOST_STATIC_ASSERT
, хотя я думаю, что все в конце концов согласились, что в мире еще есть место.