如何在 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&
> ));
请注意,此构造不能用作类型特征。
我有一个简单的元函数:
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&
> ));
请注意,此构造不能用作类型特征。