olpa
olpa

Reputation: 1227

boost::mpl::equal is always false for vector and vector_c

I'm trying to reproduce the example "3.1 Dimensional Analysis" from the book "C++ Template Metaprogramming" by Abrahams and Gurtovoy. At some moment, they compare that the "dimensions" of a value (of type mpl::vector_c) is the same as the "dimensions" of a transformed value (mpl::transform is applied to two mpl::vector_c).

By me, the compare is always false and I can't understand where I went wrong. The simplified example, without transformations:

#include <iostream>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;
using namespace boost;

using X1 = mpl::vector_c<int, 1, 2, 3>;
using X2 = mpl::vector<mpl::int_<1>, mpl::int_<2>, mpl::int_<3>>;
using CMP = mpl::equal<X1, X2>;

int main() {
  std::cout << "X1: " << type_id_with_cvr<X1>().pretty_name() << std::endl;
  std::cout << "X2: " << type_id_with_cvr<X2>().pretty_name() << std::endl;
  std::cout << "CMP: " << type_id_with_cvr<CMP>().pretty_name() << std::endl;
  std::cout << "CMP::type: " << type_id_with_cvr<CMP::type>().pretty_name() << std::endl;
  std::cout << "CMP::type::value: " << CMP::type::value << std::endl;
}

From the output:

CMP: boost::mpl::equal<boost::mpl::vector_c<int, 1l, 2l, 3l, 21474
83647l, 2147483647l, 2147483647l, 2147483647l, 2147483647l, 214748
3647l, 2147483647l, 2147483647l, 2147483647l, 2147483647l, 2147483
647l, 2147483647l, 2147483647l, 2147483647l, 2147483647l, 21474836
47l, 2147483647l>, boost::mpl::vector<mpl_::int_<1>, mpl_::int_<2>
, mpl_::int_<3>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::
na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::is_s
ame<mpl_::arg<-1>, mpl_::arg<-1> > >
CMP::type: mpl_::bool_<false>
CMP::type::value: 0

Upvotes: 1

Views: 371

Answers (1)

Stefan Moosbrugger
Stefan Moosbrugger

Reputation: 446

Ok. The reason is quite simple. There is a tiny mistake in your code. But first lets have a look of how the mpl::equal semantic is defined:

typedef equal<Sequence1,Sequence2,Pred>::type c;

c::value == true is and only if size::type::value == size::type::value and for every iterator i in [begin::type,end::type) i::type is identical to advance< begin::type, distance< begin::type,i >::type >::type.

Lets check the type of mpl::begin<X1>::type::type:

mpl_::integral_c<int, 1>

and lets check the type for mpl::begin<X2>::type::type:

mpl_::int_<1>

As you see they are not the same but the definition above states that they have to be the same if it should return true. So lets try to use intergral_c<int, X> instead of int_c<X> in the typedef of X2.

Voila (note: I used a vector3 here instead of a vector, but just for readability. It will also work with mpl::vector<...>):

X1: boost::mpl::vector3_c<int, 1, 2, 3>
X2: boost::mpl::vector3<mpl_::integral_c<int, 1>, mpl_::integral_c<int, 2>, mpl_::integral_c<int, 3> >
CMP: boost::mpl::equal<boost::mpl::vector3_c<int, 1, 2, 3>, boost::mpl::vector3<mpl_::integral_c<int, 1>, mpl_::integral_c<int, 2>, mpl_::integral_c<int, 3> >, boost::is_same<mpl_::arg<-1>, mpl_::arg<-1> > >
CMP::type: mpl_::bool_<true>
CMP::type::value: 1

UPDATE: As you can see in the comment below the user wants to compare the contained values and not just only the types. Following predicate should do what the user likes (note: for simplicity there are no checks (e.g., is_integral etc.). This should of course be done.):

template <typename T, typename V>
struct func : boost::mpl::bool_<(T::value == V::value)> {};

In order to pass it to the equal write this:

using CMP = mpl::equal<X1, X2, func<boost::mpl::_1, boost::mpl::_2> >;

Upvotes: 1

Related Questions