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

时间:2016-05-31 16:14:03

标签: c++ boost metaprogramming template-meta-programming 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是针对占位符类而不是替换类型进行评估的。如何才能正确地在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>
        >
    >
>;

由于同样的原因,这个例子显然会失败。为了使其正确,我应该改变什么?

1 个答案:

答案 0 :(得分:2)

以这种方式将类型特征写为别名并不起作用,因为它们会立即实例化。 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>>
        >
{ };

这样,std::remove_reference_t<T>无法实例化,除非我们真正尝试访问is_const_lvalue_reference<T>::type - 在_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&
    > ));

请注意,这种结构并不适用于类型特征。