why does boost mpl set allow non-unique types
Asked Answered
G

1

5

I believe my understanding of boost::mpl::set must be fundamentally flawed. I thought it only allowed unique types.

But the following code compiles:

#include <boost/mpl/set.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/accumulate.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/mpl/assert.hpp>
using namespace boost::mpl;

typedef set<long,float,long> my_set; //long repeated in set?
typedef vector<long,float,long> my_vec; //seems reasonable

typedef accumulate<
  my_set
  , int_<0>
  , plus<_1, sizeof_<_2>>
  >::type set_size;

typedef accumulate<
  my_vec
  , int_<0>
  , plus<_1, sizeof_<_2>>
  >::type vec_size;

BOOST_MPL_ASSERT_RELATION( vec_size::value, ==, sizeof(long)+sizeof(float)+sizeof(long) );
//why does the following line compile?
//shouldn't the size be sizeof(long)+sizeof(float) instead?
BOOST_MPL_ASSERT_RELATION( set_size::value, ==, sizeof(long)+sizeof(float)+sizeof(long) );
Gadwall answered 22/3, 2012 at 10:23 Comment(1)
Is typedef set<long,float,long> my_vec; meant to be typedef vector<long,float,long> my_vec;?Sukkoth
S
10

Look again at the documentation.

The list of types T1, T2, T3, ..., TN used to construct a set must not contain any duplicates. (Or put differently - the set<T1, T2, ..., TN> construct only has a well defined meaning if T1, T2, T3, ..., TN does not contain any duplicates).

Later on in the documentation there is an example of how to construct a set from a list of elements which may contain duplicates:

typedef fold<
  vector<long,float,long>
, set0<>
, insert<_1,_2>
>::type s;

BOOST_MPL_ASSERT_RELATION( size<s>::value, ==, 2 );

The set invariants are only enforced if you use the set interface to create the set.

Sukkoth answered 22/3, 2012 at 10:55 Comment(2)
An interesting point is that the result of fold<...>::type is not an mpl::set but boost::mpl::s_item<float, boost::mpl::s_item<long, boost::mpl::set0<mpl_::na> > >, I am also missing something. In Boost.Fusion this is resolved with the as_set metafunction (boost.org/doc/libs/1_59_0/libs/fusion/doc/html/fusion/container/…), but I can't find the same in Boost MPL.Infliction
Found the solution to my comment here: #28586099Infliction

© 2022 - 2024 — McMap. All rights reserved.