Передача лямбда-выражения mpl в качестве аргумента шаблона - PullRequest
0 голосов
/ 31 октября 2011

Я пытаюсь написать метафункцию, похожую на boost :: mpl :: find_if, но с той разницей, что она будет проходить по последовательности, начиная с конца. Я получаю ошибки компиляции, которые, как мне кажется, происходят из-за вычисления mpl :: lambda, переданного в качестве аргумента моей метафункции. Буду очень признателен за любые указания на то, что я делаю неправильно.

Сейчас я пытаюсь найти ленивое решение (украшая оригинал 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;
};

Проблема в том, что при попытке использовать эту функцию:

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";

Я получаю загадочные ошибки, которые, как мне кажется, происходят от лямбда-вычислений:

 /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...

Я протестировал внутреннюю часть rfind_if (без передачи лямбды в качестве аргумента шаблона), и она сработала, назвав:

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() );

дал правильные результаты

Я знаю, что моя функция далеко не эффективна, но сейчас я хочу понять проблему. Впоследствии я напишу правильную реализацию.

С наилучшими пожеланиями

1 Ответ

1 голос
/ 31 октября 2011

Насколько я понимаю, rfind_if не является причиной ошибки, но код в вопросе, кажется, разыменовывает end из test_vect.

1) Типэлементы в vector_c<int> кажутся integral_c<int>, а не int_.Таким образом, find<test_vect, int_<6>::type>::type является end из test_vect.Поэтому разыменование it_cur в deref<it_cur>::type недопустимо.

2) Если вы имеете в виду less<int_<6>, _1> под less<deref<it_cur>::type, _1>, так как test_vect не имеет такого элемента, rfind_if<...>::type снова являетсяend из test_vect.Поэтому разыменование в deref<it_swap>::type::value недопустимо.

После устранения вышеуказанных проблем код можно скомпилировать на ideone .

...