[1.32 Release] Summary of MPL changes

The HMTL version of the changelog is available at http://www.mywikinet.com/mpl/mpl_1_32_changelog.html MPL changelog for 1.32 release ****************************** The following summarizes major changes in the library interface and implementation from the previous release, with the accent on backward compatibility. Note that this is *not* a comprehensive list of all changes (yet). Apply/lambda semantics ---------------------- 1. Nullary metafunction classes are no longer special-cased, and are *not* identical to nullary metafunctions: +-------------------------+---------------+---------------------------+ | Nullary... | Before | Now | +=========================+===============+===========================+ | metafunction | ``f::type`` | ``f::type`` | +-------------------------+---------------+---------------------------+ | metafunction class | ``c::type`` | ``c::apply<>::type`` or | | | | ``c::apply::type`` [1]_ | +-------------------------+---------------+---------------------------+ This fixes a flaw in the metafunction/metafunction class algebra that long has been the major source of other inconsistencies throughout the library. 2. ``apply`` now automatically invokes ``lambda`` on its first argument, e.g. the following is well-formed now:: typedef apply< plus<_1,_1>, int_<2> >::type four; ``apply_wrap``\ *n* auxiliary metafunctions are available for rare cases when it's crutial to eliminate small overhead associated with lambda expressions while still avoiding various compiler bugs known to lurk in the obvious ``f::template apply<...>::type``. 3. Lambda implementation for broken compilers has been reworked to match as close as possible the semantics of the full-fledged version; consequently, there might be some incorrect code out there that will stop working with the new implementation. To get the detailed picture of the new apply/lambda semantics, please see the corresponding test case at http://cvs.sourceforge.net/viewcvs.py/boost/boost/libs/mpl/test/apply.cpp?vi.... .. [1] The second form is available only on fully conforming compilers. Iterator protocol ----------------- The library no loger guarantees nor relies on the direct presence of ``advance`` / ``distance`` / ``next`` / ``prior`` / ``type`` members in iterator types; the following table summarises the new requirements: +-------------------------------+-------------------------------+ | Before | Now | +===============================+===============================+ | ``i::type`` | ``deref<i>::type`` | +-------------------------------+-------------------------------+ | ``i::next`` | ``next<i>::type`` | +-------------------------------+-------------------------------+ | ``i::prior`` | ``prior<i>::type`` | +-------------------------------+-------------------------------+ | ``i::advance<n>::type`` | ``advance<i,n>::type`` | +-------------------------------+-------------------------------+ | ``i::distance<j>::type`` | ``distance<i,j>::type`` | +-------------------------------+-------------------------------+ | ``i::category`` | ``i::category`` | +-------------------------------+-------------------------------+ Sequence traits protocol ------------------------ Sequence algorithms' traits protocol has been changed to that of metafunction classes: +------------------------------------------------+------------------------------------------+ | Before | Now | +================================================+==========================================+ | *name*\ ``_traits<Tag>::algorithm<...>::type`` | *name*\ ``_impl<Tag>::apply<...>::type`` | +------------------------------------------------+------------------------------------------+ Correspondingly, if your code implemented a custom sequence, it needs to be adjusted according to the above table; for example: +-----------------------------------------------+-------------------------------------------+ | Before | Now | +===============================================+===========================================+ |:: |:: | | | | | template<> struct begin_traits<my_tag> | template<> struct begin_impl<my_tag> | | { | { | | template< typename S > struct algorithm | template< typename S > struct apply | | { | { | | typedef ... type; | typedef ... type; | | }; | }; | | }; | }; | | | | +-----------------------------------------------+-------------------------------------------+ Numeric metafunctions protocol/infrastructure --------------------------------------------- The arithmetic, comparison and bitwise metafunctions are `polymorphic`, and can operate on a variety of numeric types, including rational, fixed-point and complex numbers. The metafunctions allow `mixed arithmetic`, meaning that you can perform an operation on the arguments of different types, and the result will yeild the largest/most general of the arguments types. The infrastructure is provided to allow easy plugging of user-defined numeric types which can be made freely intermixable with predefined library types. See http://cvs.sourceforge.net/viewcvs.py/boost/boost/libs/mpl/test/numeric_ops.... for an illustrative example. If you were using MPL numeric metafunctions on your own integral wrapper class similar to ``mpl::int_``, you can plug it into the new infrustructure by extending the class with the following member:: typedef mpl::integral_c_tag tag; For example: +---------------------------------------+-------------------------------------------+ | Before | Now | +=======================================+===========================================+ |:: |:: | | | | | template< int n > struct my_int | template< int n > struct my_int | | { | { | | static int const value = n; | typedef mpl::integral_c_tag tag; | | typedef my_iny type; | static int const value = n; | | }; | typedef my_iny type; | | | }; | | | | +---------------------------------------+-------------------------------------------+ Renaming/cleanup ---------------- 1. ``apply_if`` metafunction has been renamed to ``eval_if``. 2. All ``_backward`` algorithm counterparts have been renamed to use ``reverse_`` prefix; e.g. ``fold_backward`` became ``reverse_fold``. 3. ``<boost/mpl/aux_/has_xxx.hpp>`` header has been made public and became ``<boost/mpl/has_xxx.hpp>``; correspondingly, the ``BOOST_MPL_NO_AUX_HAS_XXX`` macro was renamed to ``BOOST_MPL_CFG_NO_HAS_XXX``. 4. ``<boost/mpl/assert_is_same.hpp>`` header has been replaced by a more general ``<mpl/assert.hpp>``; the new asserts provide a significantly higher-quality diagnostics. See the table below for the new equivalents of the old macros: +-------------------------------------------+-----------------------------------------------------+ | Before | Now | +===========================================+=====================================================+ | ``BOOST_MPL_ASSERT_IS_SAME(t1, t2)`` | ``BOOST_MPL_ASSERT(( boost::is_same<t1,t2> ))`` | +-------------------------------------------+-----------------------------------------------------+ | ``BOOST_MPL_ASSERT_IS_NOT_SAME(t1, t2)`` | ``BOOST_MPL_ASSERT_NOT(( boost::is_same<t1,t2> ))`` | +-------------------------------------------+-----------------------------------------------------+ 5. All configuration macros has been renamed to include ``CFG`` prefix; in particular, ``BOOST_MPL_NO_FULL_LAMBDA_SUPPORT`` has become ``BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT``. 6. The following other public headers/components has been renamed or removed as obsolete:: iterator_tag.hpp (renamed to iterator_tags.hpp) project1st.hpp project2nd.hpp select1st.hpp select2nd.hpp Miscellaneous ------------- 1. ``vector`` has been re-implemented to support constant-time insertion at both the beginning and the end. For example, this is now well-formed:: typedef push_back<v,int>::type v1; typedef push_front<v1,int>::type v2; 2. The interface of some sequence building algorithms such as ``copy`` has been changed. Please see the corresponding headers for the details (updated docs are upcoming!). -- Aleksey Gurtovoy MetaCommunications Engineering

"Aleksey Gurtovoy" <agurtovoy@meta-comm.com> wrote in message:
MPL changelog for 1.32 release ******************************
1. Nullary metafunction classes are no longer special-cased, and are *not* identical to nullary metafunctions:
+-------------------------+---------------+---------------------------+ | Nullary... | Before | Now | +=========================+===============+===========================+ | metafunction | ``f::type`` | ``f::type`` | +-------------------------+---------------+---------------------------+ | metafunction class | ``c::type`` | ``c::apply<>::type`` or | | | | ``c::apply::type`` [1]_ | +-------------------------+---------------+---------------------------+
Great! This asymmetry has bothered me for a long time.
4. ``<boost/mpl/assert_is_same.hpp>`` header has been replaced by a more general ``<mpl/assert.hpp>``; the new asserts provide a significantly higher-quality diagnostics. See the table below for the new equivalents of the old macros:
+-------------------------------------------+----------------------------------- ------------------+
| Before | Now
|
+===========================================+=================================== ==================+
| ``BOOST_MPL_ASSERT_IS_SAME(t1, t2)`` | ``BOOST_MPL_ASSERT((
boost::is_same<t1,t2> ))`` |
+-------------------------------------------+----------------------------------- ------------------+
| ``BOOST_MPL_ASSERT_IS_NOT_SAME(t1, t2)`` | ``BOOST_MPL_ASSERT_NOT((
boost::is_same<t1,t2> ))`` |
+-------------------------------------------+----------------------------------- ------------------+ I liked BOOST_MPL_ASSERT_IS_SAME because I didn't have to use double parantheses. For the other uses now supported by BOOST_MPL_ASSERT, I could just use BOOST_STATIC_ASSERT. BTW, I remember that the reference documentation on boost consulting (or somewhere) used to include documentation of some important macros. Why not add this to the main docs? Best Regards, Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> writes:
I liked BOOST_MPL_ASSERT_IS_SAME because I didn't have to use double parantheses.
But you were out of luck if one of the types contained commas. BOOST_MPL_ASSERT_IS_SAME(T, pair<int, long>) // error! and no amount of parenthesization could fix it.
For the other uses now supported by BOOST_MPL_ASSERT, I could just use BOOST_STATIC_ASSERT.
You can always code your own ASSERT_IS_SAME. #define ASSERT_IS_SAME(x,y) BOOST_MPL_ASSERT((boost::is_same<x,y>)) There are too many other predicates that people want to assert to make is_same a special case in the library.
BTW, I remember that the reference documentation on boost consulting (or somewhere) used to include documentation of some important macros. Why not add this to the main docs?
Aleksey's working on the brand new documentation; the intention is to document everything that the user can configure. If there are particular things you want to see documented, please be specific. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:ueklijfsm.fsf@boost-consulting.com...
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
I liked BOOST_MPL_ASSERT_IS_SAME because I didn't have to use double parantheses.
But you were out of luck if one of the types contained commas.
BOOST_MPL_ASSERT_IS_SAME(T, pair<int, long>) // error!
and no amount of parenthesization could fix it.
True -- I guess that's when I switch to typedefs.
For the other uses now supported by BOOST_MPL_ASSERT, I could just use BOOST_STATIC_ASSERT.
You can always code your own ASSERT_IS_SAME.
#define ASSERT_IS_SAME(x,y) BOOST_MPL_ASSERT((boost::is_same<x,y>))
I'm aware of that.
There are too many other predicates that people want to assert to make is_same a special case in the library.
BOOST_MPL_ASSERT_IS_SAME was just a thin wrapper around BOOST_STATIC_ASSERT, right? Looking as boost/mpl/assert.hpp, I see what's going on now -- Sorry.
BTW, I remember that the reference documentation on boost consulting (or somewhere) used to include documentation of some important macros. Why not add this to the main docs?
Aleksey's working on the brand new documentation; the intention is to document everything that the user can configure. If there are particular things you want to see documented, please be specific.
BOOST_MPL_AUX_LAMBDA_SUPPORT was the main one. It appear to be part of the docs, but I don't see a link to it. Jonathan

David Abrahams writes:
"Jonathan Turkanis" <technews@kangaroologic.com> writes:
I liked BOOST_MPL_ASSERT_IS_SAME because I didn't have to use double parantheses.
But you were out of luck if one of the types contained commas.
BOOST_MPL_ASSERT_IS_SAME(T, pair<int, long>) // error!
and no amount of parenthesization could fix it.
Not to mention that when the assertion actually failed, you couldn't see what *is* the T. Now you get a beautiful error along these lines: C:\home\depot\stuff\asserts.cpp(8) : error C2664: 'boost::mpl::assertion_failed' : cannot convert parameter 1 from 'boost::mpl::failed ************boost::is_same<T,U>::* *********** ' to 'boost::mpl::assert<false>::type' with [ T=std::pair<int,char>, U=std::pair<int,long> ] A reference that is not to 'const' cannot be bound to a non-lvalue -- Aleksey Gurtovoy MetaCommunications Engineering

"Aleksey Gurtovoy" <agurtovoy@meta-comm.com> wrote
The arithmetic, comparison and bitwise metafunctions are `polymorphic`, and can operate on a variety of numeric types, including rational, fixed-point and complex numbers. The metafunctions allow `mixed
arithmetic`,
meaning that you can perform an operation on the arguments of different types, and the result will yeild the largest/most general of the arguments types. The infrastructure is provided to allow easy plugging of user-defined numeric types which can be made freely intermixable with predefined library types. See
http://cvs.sourceforge.net/viewcvs.py/boost/boost/libs/mpl/test/numeric_ops....
for an illustrative example.
Do numeric_cast template parameters have same order as boost::numeric_cast. It looks like not. (I'm afraid I dont understand mpl enough to really tell) "boost/numeric/cast.hpp" namespace boost{ template <typename Target, typename Source> some_type numeric_cast ( Source S); } //.......... namespace boost { namespace mpl { template<> struct numeric_cast< integral_c_tag,complex_tag > { template< typename N > struct apply : complex< N, integral_c< typename N::value_type, 0 > > { }; }; }} If so ... Is this not a lurking bug waiting to happen? Note however that run_time numeric_cast Source parameter would not be deducible if changed, I think. Other similar inconsistency is (I think) is_convertible). This apart the changes look to me very agreeable with my limited knowledge.I did try mpl once but I think I hit the oddities referred to above. I guess the tagged integral_c types are intended for type safety in arithmetic? If so they are extremely useful from point of bringing mpl to user. regards Andy Little

"Andy Little" <andy@servocomm.freeserve.co.uk> wrote Regarding rational_c in the \libs\mpl\doc\ref\Reference\rational_c.html IMO the result_type of the value() function could be an the integer_type, in the case where the denominator is 1. Making it a double in all cases, reduce opportunities for the compiler to optimise it after the value has ben evaluated. regards Andy Little

"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
"Andy Little" <andy@servocomm.freeserve.co.uk> wrote
Regarding rational_c in the \libs\mpl\doc\ref\Reference\rational_c.html
FWIW, these docs are now outdated. We'll have new and much more comprehensive docs for you soon, I hope! -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
"Aleksey Gurtovoy" <agurtovoy@meta-comm.com> wrote
The arithmetic, comparison and bitwise metafunctions are `polymorphic`, and can operate on a variety of numeric types, including rational, fixed-point and complex numbers. The metafunctions allow `mixed
arithmetic`,
meaning that you can perform an operation on the arguments of different types, and the result will yeild the largest/most general of the arguments types. The infrastructure is provided to allow easy plugging of user-defined numeric types which can be made freely intermixable with predefined library types. See
http://cvs.sourceforge.net/viewcvs.py/boost/boost/libs/mpl/test/numeric_ops....
for an illustrative example.
Do numeric_cast template parameters have same order as boost::numeric_cast. It looks like not.
They don't even have a similar meaning. In MPL the template parameters are tag types that identify a family of related numeric types (often specializations of the same class template).
(I'm afraid I dont understand mpl enough to really tell) "boost/numeric/cast.hpp" namespace boost{ template <typename Target, typename Source> some_type numeric_cast ( Source S); }
//..........
namespace boost { namespace mpl {
template<> struct numeric_cast< integral_c_tag,complex_tag > { template< typename N > struct apply : complex< N, integral_c< typename N::value_type, 0 > > { }; }; }}
If so ... Is this not a lurking bug waiting to happen?
No, why?
Note however that run_time numeric_cast Source parameter would not be deducible if changed, I think.
??
Other similar inconsistency is (I think) is_convertible).
Specifically?
This apart the changes look to me very agreeable with my limited knowledge.I did try mpl once but I think I hit the oddities referred to above. I guess the tagged integral_c types are intended for type safety in arithmetic?
I can't imagine what you might have in mind.
If so they are extremely useful from point of bringing mpl to user.
More questions than answers. Sorry, -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
If so ... Is this not a lurking bug waiting to happen?
No, why?
Note however that run_time numeric_cast Source parameter would not be deducible if changed, I think.
??
Other similar inconsistency is (I think) is_convertible).
Specifically?
#include "boost/numeric/converter.hpp" #include "boost/type_traits/is_convertible.hpp" #include <complex> #include <cassert> template<typename Target, typename Source> Target do_conv( Source const & s) { typedef boost::numeric::converter<Target,Source> conv; assert((boost::is_convertible<Target,Source>::value) ); typedef conv::result_type result_type; result_type res = conv()(s); return res; } int main() { do_conv<int>(2.); /* once a year*/ do_conv<std::complex<double> >(2.); } regards Andy Little
participants (4)
-
Aleksey Gurtovoy
-
Andy Little
-
David Abrahams
-
Jonathan Turkanis