如何在 Boost.MPL 中使用嵌套元函数

How to use nested metafunctions in Boost.MPL?

本文关键字:嵌套 函数 Boost MPL      更新时间:2023-10-16

>我有一个简单的元函数:

template <typename T>
using is_const_lvalue_reference = mpl::and_<
    std::is_lvalue_reference<T>,
    std::is_const<typename std::remove_reference<T>::type>
>;

显然,如果T是 MPL 占位符,则它不起作用,因为remove_reference是针对占位符类而不是替换类型进行评估的。如何正确执行此操作才能在 MPL 算法中使用此元函数?

更新:建议的解决方案是用结构替换别名,这将延迟模板实例化std::remove_reference。问题是,如何在不使用任何帮助程序结构的情况下延迟内联实例化?

template <typename Sequence>
using are_const_lvalue_references = mpl::fold<
    Sequence,
    mpl::true_,
    mpl::and_<
        mpl::_1,
        mpl::and_<
            std::is_lvalue_reference<mpl::_2>,
            std::is_const<typename std::remove_reference<mpl::_2>::type>
        >
    >
>;

由于同样的原因,此示例显然会失败。我应该更改什么才能使其正确?

以这种方式将类型特征编写为别名是行不通的,因为它们会立即实例化。 is_const_lvalue_reference<_1> 完全mpl::and_<std::is_lvalue_reference<_1>, std::is_const<_1>>(因为_1不是引用类型) - 这总是false,因为左值引用不是const。不过写false_非常棘手的方法!

相反,您必须延迟实例化。只需使类型特征继承自mpl::and_而不是为其别名:

template <class T>
struct is_const_lvalue_reference
    : mpl::and_<
        std::is_lvalue_reference<T>,
        std::is_const<std::remove_reference_t<T>>
        >
{ };

这样,除非我们实际尝试访问is_const_lvalue_reference<T>::type,否则std::remove_reference_t<T>不会被实例化 - 直到_1被替换为 apply 中的真实类型才会发生这种情况。

<小时 />

或者,由于apply<>将在查找占位符的位置调用::type,因此您可以自己删除::type的显式调用。所以这有效:

BOOST_MPL_ASSERT(( mpl::apply<
    std::is_const<std::remove_reference<_1>>,
    int const&
    > ));

或原始表达式:

BOOST_MPL_ASSERT(( mpl::apply<
    mpl::and_<
        std::is_lvalue_reference<_1>,
        std::is_const<std::remove_reference<_1>>
    >,
    int const&
    > ));

请注意,此构造不能用作类型特征。