Boost logo

Boost Users :

Subject: Re: [Boost-users] Bad interaction between lexical_cast and MPL with VS2013
From: Edward Diener (eldiener_at_[hidden])
Date: 2015-08-03 14:05:29

On 8/1/2015 1:47 PM, Roger Leigh wrote:
> Hi folks,
> I have some code making use of both Boost MPL (and Variant) with
> occasional use of lexical_cast in some translation units. This is
> working fine on Linux/Unix/MacOS X with a wide range of GCC and clang
> versions. However, when porting to Windows with MS Visual Studio 2013
> and Boost 1.58, I've encountered an unexpected and subtle interaction
> with the MPL and Boost headers. If I include them in the "wrong" order
> it leads to bizarre compile errors.
> After many hours of testing, I've reduced the failure down to the
> minimal testcase below. In the code sample below, there are two
> #includes for boost/lexical_cast.hpp. If the first is uncommented,
> compiling fails. If this is commented and the second is uncommented,
> compiling succeeds! The odd thing: the critical place is before and
> after defining BOOST_MPL_LIMIT_VECTOR_SIZE. In the failure case the
> limit size is 20, when succeeding it's 40. The code below requires more
> than 20 to successfully compile.

Changing the MPL limits should ideally be done before including any MPL
header files. Since many Boost libraries use MPL this usually means that
changing the MPL limits should ideally be done before including any
Boost header files.

I realize that this is not necessarily possible if you wish to change
MPL limits in your own library since you can't control the order that an
end-user will include your library's header file in a TU.

I will look into this problem of why changing the MPL limits causes
compiler errors in VS2013, but can you please create a Boost trac item
concerning this problem. Recently there has been some activity in MPL
concerning the issue of changing MPL limits so it is barely possible
this is fixed in the recent source.

> While it's fairly obvious with hindsight that lexical_cast is indirectly
> including boost/mpl/limits/vector.hpp which is defaulting the limit to
> 20, the fact that the behaviour is differing between compilers is a bit
> unexpected, particularly since I don't want to mess with the limit if
> already set in case the users of my library need a higher limit, but
> they might have used lexical_cast themselves.
> Has anyone else run into this type of problem before? It's also made me
> realise that using variant with MPL lists might be problematic if the
> end user changes the limit and this changes the underlying type? Should
> I just use vector40.hpp and ignore the limit?

You can do this since MPL normally ships with up to 50.

> If I did this, do I need
> to worry about the intermediate types in the code below, or do I just
> need to use vector40 in place of vector<> (or in place of
> vector0<>)

 From the MPL docs:

"each numbered sequence form accepts the exact number of elements that
is encoded in the name of the corresponding class template".

So using vector40 means you can have up to 40 types in the vector.

> --I'm unsure how insert_range knows which type to use or is it
> vector0 in this case and I should be "allocating" space by using a
> different type? [I am using vector<> in reality but tried vector0 here
> to see if it made a difference]

You shouldn't have to worry about intermediate types or insert_range.
Any MPL algorithm knows how many types are in a sequence, just like you
know (size<v>::type).

> Thanks all,
> Roger
> ----source--------------------------------------------------------------
> #include <string>
> #include <vector>
> #include <cstdint>
> /// Disable MPL header preprocessing (to allow the following macros to
> be modified).
> # endif
> #include <boost/lexical_cast.hpp>
> /// MPL vector size limit increase.
> # endif
> //#include <boost/lexical_cast.hpp>
> /// MPL list size limit increase.
> # endif
> #include <boost/mpl/insert_range.hpp>
> #include <boost/mpl/joint_view.hpp>
> #include <boost/mpl/transform_view.hpp>
> #include <boost/mpl/vector.hpp>
> #include <boost/mpl/vector/vector0.hpp>
> #include <boost/version.hpp>
> #if BOOST_VERSION >= 105800
> # include <boost/type_traits/remove_cv.hpp>
> #endif
> typedef boost::mpl::vector<std::string,
> bool> non_numeric_types;
> typedef boost::mpl::vector<uint8_t,
> uint16_t,
> uint32_t,
> uint64_t,
> int8_t,
> int16_t,
> int32_t,
> int64_t> integer_types;
> typedef boost::mpl::vector<float,
> double,
> long double> float_types;
> typedef boost::mpl::joint_view<integer_types,
> float_types>::type numeric_types_view;
> typedef boost::mpl::joint_view<non_numeric_types,
> numeric_types_view>::type basic_types_view;
> template<typename T>
> struct make_vector
> {
> typedef std::vector<T> type;
> };
> typedef boost::mpl::transform_view<basic_types_view,
> make_vector<boost::mpl::_1> >::type list_types_view;
> typedef boost::mpl::joint_view<basic_types_view, list_types_view>
> all_types_view;
> typedef boost::mpl::insert_range<boost::mpl::vector0<>,
> boost::mpl::end<boost::mpl::vector0<> >::type, all_types_view>::type
> discriminated_types;


Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at