我有一个简单的元函数:
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>
>
>
>;
由于同样的原因,这个例子显然会失败。为了使其正确,我应该改变什么?
答案 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&
> ));
请注意,这种结构并不适用于类型特征。