[mpl] Nested BOOST_MPL_ASSERT fails on VC11

AMDG I just ran into the following bug: template<class T> struct test : T { BOOST_MPL_ASSERT((T)); }; BOOST_MPL_ASSERT((test<T>)); I've reworked BOOST_MPL_ASSERT to avoid the problem in the attached patch. Okay to commit? In Christ, Steven Watanabe

I'm not qualified to answer this one; Aleksey? on Wed Oct 10 2012, Steven Watanabe <watanabesj-AT-gmail.com> wrote:
AMDG
I just ran into the following bug:
template<class T> struct test : T { BOOST_MPL_ASSERT((T)); }; BOOST_MPL_ASSERT((test<T>));
I've reworked BOOST_MPL_ASSERT to avoid the problem in the attached patch. Okay to commit?
In Christ, Steven Watanabe
Index: boost/mpl/assert.hpp =================================================================== --- boost/mpl/assert.hpp (revision 80856) +++ boost/mpl/assert.hpp (working copy) @@ -34,6 +34,9 @@ #include <boost/config.hpp> // make sure 'size_t' is placed into 'std' #include <cstddef>
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1700) +#include <boost/mpl/if.hpp> +#endif
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \ || (BOOST_MPL_CFG_GCC != 0) \ @@ -131,9 +134,39 @@
#endif
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
-#if !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER) +template<class Pred> +struct extract_assert_pred;
+template<class Pred> +struct extract_assert_pred<void(Pred)> { typedef Pred type; }; + +template<class Pred> +struct eval_assert { + typedef typename extract_assert_pred<Pred>::type P; + typedef typename P::type p_type; + typedef typename ::boost::mpl::if_c<p_type::value, + AUX778076_ASSERT_ARG(assert<false>), + failed ************ P::************ + >::type type; +}; + +template<class Pred> +struct eval_assert_not { + typedef typename extract_assert_pred<Pred>::type P; + typedef typename P::type p_type; + typedef typename ::boost::mpl::if_c<!p_type::value, + AUX778076_ASSERT_ARG(assert<false>), + failed ************ ::boost::mpl::not_<P>::************ + >::type type; +}; + +template< typename T > +T make_assert_arg(); + +#elif !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER) + template< bool > struct assert_arg_pred_impl { typedef int type; }; template<> struct assert_arg_pred_impl<true> { typedef void* type; };
@@ -211,6 +244,7 @@
BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
// BOOST_MPL_ASSERT((pred<x,...>))
@@ -219,6 +253,38 @@ std::size_t \ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ boost::mpl::assertion_failed<false>( \ + boost::mpl::make_assert_arg< \ + typename boost::mpl::eval_assert<void pred>::type \ + >() \ + ) \ + ) \ + ) \ +/**/ + +// BOOST_MPL_ASSERT_NOT((pred<x,...>)) + +#define BOOST_MPL_ASSERT_NOT(pred) \ +BOOST_MPL_AUX_ASSERT_CONSTANT( \ + std::size_t \ + , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ + boost::mpl::assertion_failed<false>( \ + boost::mpl::make_assert_arg< \ + typename boost::mpl::eval_assert_not<void pred>::type \ + >() \ + ) \ + ) \ + ) \ +/**/ + +#else + +// BOOST_MPL_ASSERT((pred<x,...>)) + +#define BOOST_MPL_ASSERT(pred) \ +BOOST_MPL_AUX_ASSERT_CONSTANT( \ + std::size_t \ + , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ + boost::mpl::assertion_failed<false>( \ boost::mpl::assert_arg( (void (*) pred)0, 1 ) \ ) \ ) \ @@ -250,6 +316,8 @@ /**/ #endif
+#endif + // BOOST_MPL_ASSERT_RELATION(x, ==|!=|<=|<|>=|>, y)
#if defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES) Index: libs/mpl/test/assert.cpp =================================================================== --- libs/mpl/test/assert.cpp (revision 80856) +++ libs/mpl/test/assert.cpp (working copy) @@ -71,6 +71,17 @@ } };
+template<class T> +struct nested : boost::mpl::true_ { + BOOST_MPL_ASSERT(( boost::is_pointer<T*> )); + BOOST_MPL_ASSERT_NOT(( boost::is_same<void,T> )); + BOOST_MPL_ASSERT_RELATION( sizeof(T*), >, 1 ); + BOOST_MPL_ASSERT_MSG( true, GLOBAL_SCOPE_ERROR, (int,long) ); +}; + +BOOST_MPL_ASSERT(( nested<int> )); +BOOST_MPL_ASSERT_NOT(( boost::mpl::not_<nested<unsigned> > )); + int main() { her<void> h;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- Dave Abrahams BoostPro Computing Software Development Training http://www.boostpro.com Clang/LLVM/EDG Compilers C++ Boost

AMDG On 10/11/2012 05:03 PM, Dave Abrahams wrote:
I'm not qualified to answer this one; Aleksey?
on Wed Oct 10 2012, Steven Watanabe <watanabesj-AT-gmail.com> wrote:
I just ran into the following bug:
template<class T> struct test : T { BOOST_MPL_ASSERT((T)); }; BOOST_MPL_ASSERT((test<T>));
I've reworked BOOST_MPL_ASSERT to avoid the problem in the attached patch. Okay to commit?
If no one objects within the next day or so, I'm going to go ahead with it. The new code is #ifdef'ed for msvc-11 only, so it shouldn't cause problems on any other compiler. (I've tested with gcc and clang as well.) In Christ, Steven Watanabe

[Steven Watanabe]
The new code is #ifdef'ed for msvc-11 only, so it shouldn't cause problems on any other compiler.
If you'd like to remove this workaround someday, and can reduce this to a Boost-free repro, I can file a compiler bug (if you don't want to go through Connect). STL

AMDG On 10/15/2012 02:08 PM, Stephan T. Lavavej wrote:
[Steven Watanabe]
The new code is #ifdef'ed for msvc-11 only, so it shouldn't cause problems on any other compiler.
If you'd like to remove this workaround someday, and can reduce this to a Boost-free repro, I can file a compiler bug (if you don't want to go through Connect).
I was planning to submit a bug report, but I haven't had time to reduce it yet. In Christ, Steven Watanabe
participants (3)
-
Dave Abrahams
-
Stephan T. Lavavej
-
Steven Watanabe