Boost.MPL: Is it possible to apply a variable substitution without evaluating the lambda-expression?
I am using BOOST_MPL_ASSERT to assert a lambda-expression applied to a sequence of types by folding the lambda-expression onto a sequence of types (see code and continue discussion below). template<class predicate, class argument> struct mpl_assert { typedef typename apply<predicate, argument>::type type; BOOST_MPL_ASSERT((type)); }; template<class pred, class xs> struct assert_for_all : foldr< mpl_assert<typename lambda<pred>::type, _>, true_, xs
{};
The foldr metafunction is a strict version of Haskell's foldr, i.e., MPL's reverse_fold with parameters passed in the order that Haskell's foldr passes parameters. The distinction isn't important for this discussion, so don't dwell on that detail. My intent is that if the lambda-expression is false for one of the types in the sequence, then the lambda-expression applied to the "bad" argument is printed in a compile-time error. However, what gets printed is the result of the lambda-expression applied to the bad argument: integral_constant<bool, false>, which is very uninformative. If the definition of mpl_assert is changed to the following: template<class predicate, class argument> struct mpl_assert { typedef typename apply<predicate, argument>::type type; BOOST_MPL_ASSERT((apply<predicate, argument>)); }; ...then what gets printed is the unevaluated application of a lambda-expression to the bad argument. While this is more informative, it is still too messy because the type is a lambda-expression containing placeholders. The most desirable type to have printed would be the lambda-expression after placeholder substitution, but before further evaluation. For example, imagine: typedef assert_for_all<is_same<foo, _>, boost::mpl::vector<foo, bar>
::type type;
...the first definition of mpl_assert prints the following uninformative type in the displayed error: boost::integral_constant<bool, false> ...the second definition of mpl_assert prints the more descriptive but overly messy type: boost::mpl::apply<boost::mpl::protect<boost::mpl::bind2<boost::mpl::quote2<boost::is_same, mpl_::void_>, foo, mpl_::arg<-0x000000001> >, 0>, bar, mpl_::na, mpl_::na, mpl_::na, mpl_::na> ...but what I want to have printed is the type: boost::is_same<foo, bar> Boost.MPL is already calculating such a type, because apply<is_same<foo, _>, bar> returns is_same<foo, bar>::type, so the needed type is there... but does Boost.MPL provide a means of accessing it as opposed to accessing its ::type field?
AMDG Luke Simon wrote:
I am using BOOST_MPL_ASSERT to assert a lambda-expression applied to a sequence of types by folding the lambda-expression onto a sequence of types (see code and continue discussion below).
template<class predicate, class argument> struct mpl_assert { typedef typename apply<predicate, argument>::type type; BOOST_MPL_ASSERT((type)); };
template<class pred, class xs> struct assert_for_all : foldr< mpl_assert<typename lambda<pred>::type, _>, true_, xs
{};
<snip>
...but what I want to have printed is the type:
boost::is_same<foo, bar>
Boost.MPL is already calculating such a type, because apply<is_same<foo, _>, bar> returns is_same<foo, bar>::type, so the needed type is there... but does Boost.MPL provide a means of accessing it as opposed to accessing its ::type field?
MPL doesn't provide such a metafunction. Note that MPL doesn't actually calculate this in the process of evaluating lambda expressions, because of nesting. For example, is_same<foo, remove_reference<_> > does not ever use is_same<foo, remove_reference<bar> > You might try using protect instead of lambda in assert_for_all. In Christ, Steven Watanabe
participants (2)
-
Luke Simon
-
Steven Watanabe