why does this lambda expression not work

following the book C++ Template Metaprogramming I find the following lambda expression that does not do what it's supposed to:

1
2
3
4
5
6
7
using argument_types = mpl::vector<int, long, std::string>;

using parameter_types = boost::mpl::transform < argument_types,
	mpl::if_<
	mpl::bool_<boost::is_scalar<_1>::value || boost::is_reference<_1>::value>,
	mpl::identity<_1>,
	boost::add_reference<boost::add_const<_1>>>>::type;


The resultinf parameter_types has these members: const int&, const long&, const std::string& and is thus WRONG.

The result should not change int and long since they are scalar.
Somehow is_scalar is evaluated with the type _1 which is not scalar nor a reference and thus produce wrong result.

The previous code can be corrected by the following alternative:



1
2
3
4
5
using parameter_types_correct = boost::mpl::transform < argument_types,
	mpl::if_<
	mpl::or_<boost::is_scalar<_1>, boost::is_reference<_1>>,
	mpl::identity<_1>,
	boost::add_reference<boost::add_const<_1>>>>::type;



Can somebody explain why this last code works and not the former?
Is it the presence of ::value in the first code that operates directly on the type _1?

Regards,
Juan
I have no idea about MPL, but I would guess that boost::is_scalar<_1>::value and boost::is_reference<_1>::value are evaluated eagerly before being passed to mpl::bool_, thus constructing a literal bool that's independent of the argument type being considered during boost::mpl::transform, while mpl::or_<boost::is_scalar<_1>, boost::is_reference<_1>> constructs a lazily evaluated expression that can be applied to the argument types.
Thanks!! That's it!
Registered users can post here. Sign in or register to post.