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:
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?
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.