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

How to use nested metafunctions in Boost.MPL?

我有一个简单的元函数:

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 是针对占位符 class 而不是替代类型计算的。如何正确执行此操作才能在 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&
    > ));

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