Disclaimer: I am far from an MPL expert, so I cannot promise that this is the best way to solve this problem (or even if it is correct, it seems to work at least).
According to the documentation, the first parameter / argument for mpl::apply should be a Lambda expression, and this can be either a Metafunction class or a Placeholder expression. A quick google search led me to this post . According to this post, mpl::is_lambda_expression allows mpl::is_lambda_expression to determine if a type is a placeholder expression. In Boost.TTI (that is, from version 1.54) you can find a metafound that does exactly what you want. This metafound is boost::tti::detail::is_lambda_expression and can be found in boost/tti/detail/dlambda.hpp . In the example below, I used the same macro that TTI uses to determine if a type is a Metafunction class.
Running on Coliru.
#include <iostream> #include <typeinfo> #include <boost/utility.hpp> #include <boost/mpl/apply.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/plus.hpp> namespace mpl=boost::mpl; /* //This is another way to do it template <typename T, typename Enable=void> struct is_apply_able : mpl::false_ {}; template <typename T> struct is_apply_able<T,typename boost::enable_if<mpl::is_lambda_expression<T> >::type> : mpl::true_ {}; BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(is_metafunction_class, apply, false) template <typename T> struct is_apply_able<T,typename boost::enable_if<is_metafunction_class<T> >::type> : mpl::true_ {};*/ BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(is_metafunction_class, apply, false) template <typename T> struct is_apply_able : mpl::or_<is_metafunction_class<T>,mpl::is_lambda_expression<T> > {}; struct plus_two { template <typename Number> struct apply { typedef typename mpl::plus<Number,mpl::int_<2> >::type type; }; }; template <typename T> struct Foo {}; template <typename Partial, typename T> struct maybe_apply : mpl::eval_if<is_apply_able<Partial>, mpl::apply<Partial, T>, mpl::identity<Partial> > { }; int main() { std::cout << typeid(maybe_apply<Foo<mpl::_1>,int>::type).name() << std::endl; std::cout << typeid(maybe_apply<plus_two,mpl::int_<1> >::type).name() << std::endl; std::cout << typeid(maybe_apply<Foo<float>,int>::type).name() << std::endl; }
source share