Reputation: 917
I'm trying to write a metafunction similar to boost::mpl::find_if but with the difference that it will traverse the sequence starting from the end. I am getting compilation errors which I guess come from computation of mpl::lambda passed as an argument of my metafunction. I would be very grateful on any pointers on what I am doing wrong.
Right now I'm trying a lazy solution (decorating the original find_if):
#include <boost/mpl/reverse.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/distance.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/advance.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/lambda.hpp>
using boost::mpl::reverse;
using boost::mpl::find_if;
using boost::mpl::distance;
using boost::mpl::end;
using boost::mpl::advance;
using boost::mpl::prior;
using boost::mpl::lambda;
template<typename SEQ, typename pred>
struct rfind_if {
private:
// find the element in the reversed container
typedef typename reverse<SEQ>::type rev_SEQ;
typedef typename lambda<pred>::type expanded_pred;
typedef typename find_if<rev_SEQ, expanded_pred>::type rev_iter;
// compute the distance of the iterator
typedef typename distance<rev_iter, typename end<rev_SEQ>::type >::type dist;
public:
//compute the iterator
typedef typename advance<typename begin<SEQ>::type, typename prior<dist>::type>::type type;
};
The problem is that When trying to use this function:
typedef vector_c<int, 1, 2, 3, 6, 5, 4>::type test_vect;
typedef find<test_vect, int_<6>::type>::type it_cur;
typedef rfind_if<test_vect, lambda<less<deref<it_cur>::type, _1> >::type >::type it_swap;
std::cout << "it_swap=" << deref<it_swap>::type::value << "\n\n";
I get cryptic errors which, I guess, come from lambda computations:
/usr/include/boost/mpl/aux_/preprocessed/gcc/less.hpp:60: error: no type named ‘tag’ in ‘struct mpl_::void_’ (some more template noise)
/usr/include/boost/mpl/not.hpp:43: error: ‘value’ is not a member of ‘boost::mpl::aux::nested_type_wknd<boost::mpl::aux::iter_apply1 (some more template noise)
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:62: error: no type named ‘type’ in ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred (some more template noise)
...and much more...
I've tested the internals of rfind_if (without passing the lambda as a template argument) and it worked, naming:
typedef vector_c<int, 1, 2, 3, 6, 5, 4>::type test_vect;
typedef boost::mpl::reverse<test_vect>::type rev_SEQ;
typedef find_if<rev_SEQ, less<int_<5>, _1> >::type rev_iter;
typedef distance<rev_iter, end<rev_SEQ>::type >::type dist;
typedef advance<begin<test_vect>::type, prior<dist>::type>::type it_begin;
boost::mpl::for_each< rev_SEQ >( value_printer() );
produced correct results
I know that my function is far from efficient, but right now I want to understand the problem. I will write a proper implementation afterwards.
Best Regards
Upvotes: 0
Views: 785
Reputation: 11669
As far as I see, rfind_if
isn't the cause of the error, but the code in
the question seems to dereference the end
of test_vect
.
1)
The type of the elements in vector_c<int>
seems integral_c<int>
, not
int_
.
So find<test_vect, int_<6>::type>::type
is the end
of test_vect
.
Therefore dereferencing the it_cur
in deref<it_cur>::type
is invalid.
2)
If you mean less<int_<6>, _1>
by less<deref<it_cur>::type, _1>
,
since test_vect
doesn't have such an element, rfind_if<...>::type
is
again the end
of test_vect
.
So dereferencing it in deref<it_swap>::type::value
is invalid.
After fixing the above issues, the code could be compiled on ideone.
Upvotes: 1