考虑对std::any_of
的Boost.MPL样式元编程版本进行以下尝试
#include <iostream> // cout
#include <type_traits> // is_base_of, is_pod
#include <boost/mpl/apply.hpp> // apply
#include <boost/mpl/fold.hpp> // fold
#include <boost/mpl/lambda.hpp> // lambda, _1, _2
#include <boost/mpl/logical.hpp> // and_, true_
#include <boost/mpl/vector.hpp> // vector
template
<
typename Sequence,
typename Pred
>
struct all_of
:
boost::mpl::fold<
Sequence,
boost::mpl::true_,
boost::mpl::lambda<
boost::mpl::and_<
boost::mpl::_1,
boost::mpl::apply< Pred, boost::mpl::_2 >
>
>
>
{};
typedef int P1; typedef char P2; typedef float P3;
typedef boost::mpl::vector<
P1, P2, P3
> pod_types;
struct B {}; struct D1: B {}; struct D2: B {}; struct D3: B {};
typedef boost::mpl::vector<
D1, D2, D3
> derived_types;
int main()
{
std::cout << (std::is_pod<P1>::value) << '\n'; // true
std::cout << (std::is_pod<P2>::value) << '\n'; // true
std::cout << (std::is_pod<P3>::value) << '\n'; // true
std::cout << (
all_of<
pod_types,
std::is_pod< boost::mpl::_1 >
>::type::value // true
) << '\n';
std::cout << (std::is_base_of<B, D1>::value) << '\n'; // true
std::cout << (std::is_base_of<B, D2>::value) << '\n'; // true
std::cout << (std::is_base_of<B, D3>::value) << '\n'; // true
std::cout << (
all_of<
derived_types,
std::is_base_of< B, boost::mpl::_1 >
>::type::value // false (but should be true)
) << '\n';
return 0;
}
输出结果为:1 1 1 1 1 1 1 10。即,以谓词传递的
all_of
最终调用std::is_base_of
会生成false。为什么这不起作用?显然,基类B
没有正确地绑定(bind)到谓词。我应该如何传递二进制谓词? mpl::lambda或mpl::bind的某种组合?更新
根据Luc Touraille的出色答案,这是我的问题的无lambda解决方案,另外还包括
none_of
和any_of
的编译时版本 template<typename Sequence, typename Pred>
struct all_of
:
std::is_same< typename
boost::mpl::find_if<
Sequence,
boost::mpl::not_<Pred>
>::type, typename
boost::mpl::end<Sequence>::type
>
{};
template<typename Sequence, typename Pred>
struct none_of
:
all_of< Sequence, boost::mpl::not_< Pred > >
{};
template<typename Sequence, typename Pred>
struct any_of
:
boost::mpl::not_< none_of< Sequence, Pred > >
{};
最佳答案
#include <type_traits>
#include <boost/mpl/end.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/logical.hpp>
template
<
typename Sequence,
typename Pred
>
struct all_of
:
std::is_same< typename
boost::mpl::end< Sequence >::type, typename
boost::mpl::find_if<
Sequence,
boost::mpl::not_< Pred >
>::type
>
{};
如果要坚持使用
fold
,则需要在调用 lambda
之前使用protect将谓词转换为元函数,以使用this discussion on the Boost mailing list参数:boost::mpl::apply< typename
boost::mpl::lambda< Pred >::type,
boost::mpl::_2
>
但是,您会注意到这也不起作用。我不知道为什么会这样,我认为它与
apply
有关。显然,lambda
的奇偶性大于apply1
支持的奇偶性。无论如何,一个简单的解决方法是使用ojit_a而不是apply
。这是完整的解决方案:template
<
typename Sequence,
typename Pred
>
struct all_of
: boost::mpl::fold<
Sequence,
boost::mpl::true_,
boost::mpl::and_<
boost::mpl::_1,
boost::mpl::apply1< typename
boost::mpl::lambda< Pred >::type,
boost::mpl::_2
>
>
>
{};
关于c++ - 二进制谓词应如何传递给用户定义的Boost.MPL算法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9344599/