How to check if type is mpl :: apply-able?

If I have a type T that looks like Foo<mpl::_1> , I can do mpl::apply<T, int>::type to get Foo<int> .

But if T is a full type, for example, Foo<int> , then mpl::apply<T, int>::type will not compile.

I want to write a metafunction that will apply the type, if possible, otherwise return the type. So something like:

 template <typename Partial, typename T> struct maybe_apply : eval_if_c<??????, mpl::apply<Partial, T>, mpl::identity<Partial>> { }; 

What can I add to this so that it does what I want?

+4
source share
1 answer

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; } 
+2
source

Source: https://habr.com/ru/post/1499874/


All Articles