使用 boost::mpl::eval_if 延迟评估

问题描述 投票:0回答:1

我有以下代码:

#include <boost/mpl/apply.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/mpl/greater.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/multiplies.hpp>

#include <boost/type_traits/is_scalar.hpp>

template <typename N, typename Predicate >
struct next_if 
    : boost::mpl::eval_if<
            typename boost::mpl::apply<Predicate, N>::type, 
            // boost::mpl::apply<Predicate, N>,
            boost::mpl::next<N>,
            boost::mpl::identity<N>
            >
{};

template <typename N>
struct predic : boost::mpl::bool_<false>
{
};

template <int N>
struct predic <boost::mpl::int_<N>> : boost::mpl::bool_< (N > 0 && N < 100) >
{
};

int main()
{
    static_assert(std::is_same_v<next_if<boost::mpl::int_<10>, predic<boost::mpl::_1>>::type, boost::mpl::int_<11>>, "");

    return 0;
}

通过传递 static_assert 可以正确编译,如 godbolt 所示:https://godbolt.org/z/zcE9q8Trr .

但是,如果我注释掉“typename boost::mpl::apply::type,”并取消注释“// boost::mpl::apply,”,则编译失败,因为mpl_::arg<1>的早期评估。

/opt/compiler-explorer/libs/boost_1_64_0/boost/mpl/if.hpp: In instantiation of 'struct boost::mpl::if_<boost::mpl::apply<predic<mpl_::arg<1> >, mpl_::int_<10>, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::next<mpl_::int_<10> >, boost::mpl::identity<mpl_::int_<10> > >':
/opt/compiler-explorer/libs/boost_1_64_0/boost/mpl/eval_if.hpp:37:41:   required from 'struct boost::mpl::eval_if<boost::mpl::apply<predic<mpl_::arg<1> >, mpl_::int_<10>, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::next<mpl_::int_<10> >, boost::mpl::identity<mpl_::int_<10> > >'
<source>:19:8:   required from 'struct next_if<mpl_::int_<10>, predic<mpl_::arg<1> > >'
<source>:40:87:   required from here
/opt/compiler-explorer/libs/boost_1_64_0/boost/mpl/aux_/static_cast.hpp:24:47: error: 'value' is not a member of 'boost::mpl::apply<predic<mpl_::arg<1> >, mpl_::int_<10>, mpl_::na, mpl_::na, mpl_::na, mpl_::na>'
   24 | #   define BOOST_MPL_AUX_STATIC_CAST(T, expr) static_cast<T>(expr)
      |                                               ^~~~~~~~~~~~~~~~~~~~

问题是:为什么不“typename boost::mpl::apply::type,”强制对 boost::placeholder mpl_::arg<1> 进行早期评估来计算 boost::mpl 的类型: :apply,但是看起来更无辜的“boost::mpl::apply”会代替吗?

谢谢!

c++ boost template-meta-programming
1个回答
0
投票
#include <type_traits>

#include <boost/mpl/apply.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/mpl/greater.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/multiplies.hpp>

#include <boost/type_traits/is_scalar.hpp>

template <typename N, typename Predicate >
struct next_if 
    : boost::mpl::eval_if<
            boost::mpl::apply<Predicate, N>,
            boost::mpl::next<N>,
            boost::mpl::identity<N>
            >
{};


struct predic2
{
    template <typename N>
    struct apply : boost::mpl::bool_<boost::mpl::greater<N, boost::mpl::int_<0>>::value && boost::mpl::less<N, boost::mpl::int_<100>>::value>
    {
    };
} ;

int main()
{
    static_assert(std::is_same_v<next_if<boost::mpl::int_<10>, predic2>::type, boost::mpl::int_<11>>, "");

    return 0;
}

但是,从上面的代码来看, predic2boost::mpl::apply 配合得很好。

在我使用 g++ -E 编译代码以生成源代码而不是编译成最终二进制文件之后: g++ -E --std=c++17 -I ~/workspace/boost_1_82_0 test.cpp

struct predic 的情况下,看起来 boost::mpl::apply 继承自 boost::mpl::lambda::apply ,而没有定义 type

struct predic2 的情况下,boost::mpl::apply 直接继承自 predic2::apply,在我的示例中,定义了 type

© www.soinside.com 2019 - 2024. All rights reserved.