Реализация C ++ 11 лямбда с использованием boost

0

У меня есть проблема с попыткой конвертировать фрагмент кода С++ 11 для повышения.

Предположим, что у меня есть простой класс:

class C
{

public:

    typedef std::vector<std::string> Info;

public:

    explicit C(Info const& info)
        : info_(info)
    {}

    std::string text(Info::size_type i) const
    {
        return info_[i];
    }

private:

    Info info_;

};

Теперь, если у меня есть вектор классов C, я хотел бы получить максимальную ширину определенного элемента C :: Info, используя алгоритм std :: max_element.

С lambdas С++ 11 я мог бы сделать это следующим образом:

C::Info::size_type const Info_0 = 0;
C::Info::size_type const Info_1 = 1;
C::Info::size_type const Info_2 = 2;

int get_max_width(std::vector<C> const& c_vec, C::Info::size_type info_n)
{
    std::vector<C>::const_iterator max = std::max_element(c_vec.cbegin(), c_vec.cend(),
        [info_n](C const& lhs, C const& rhs)
        { return lhs.text(info_n).length() < rhs.text(info_n).length(); });

    return max != c_vec.end() ? max->text(info_n).length() : 0;
}

Но проблема в том, что я не могу использовать С++ 11, поэтому мне нужно идти с повышением.

На данный момент код, который я смог придумать, выглядит следующим образом:

int get_max_width(std::vector<C> const& c_vec, C::Info::size_type info_n)
{
    std::vector<C>::const_iterator max = std::max_element(c_vec.cbegin(), c_vec.cend(),
        boost::lambda::bind(&C::text, boost::lambda::_1, boost::lambda::var(info_n)) <
        boost::lambda::bind(&C::text, boost::lambda::_2, boost::lambda::var(info_n)));

    return max != c_vec.end() ? max->text(info_n).length() : 0;
}

Хотя это явно не то, что я хочу. Сравнение выполняется над объектами std :: string, и я застреваю, пытаясь понять, как вызвать эту функцию length()...

Ваша помощь весьма приветствуется.

  • 6
    Простите, но зачем? Вы можете просто определить правильный функтор, чтобы сделать ту же работу.
  • 0
    @40two 40two Недостаток решения functor состоит в том, что в C ++ 03 требуются типы, используемые для аргументов шаблона, чтобы иметь внешнюю связь. Это означает, что функтор не может быть определен локально в get_max_width() . Не огромная сделка, но больше раздражающего ограничения.
Показать ещё 2 комментария
Теги:
c++11
lambda
boost

2 ответа

3
Лучший ответ

Не обязательно ответ, который вы запрашиваете, но для подхода non С++ 11 полезно знать, что лямбда-выражения похожи на структуры с помощью оператора функции.

Таким образом, ваш пример может быть реализован примерно так:

struct lambda_max
{
    const C::Info::size_type& info_n;

    lambda_max(const C::Info::size_type& info_n):info_n(info_n) {}

    bool operator()(C const& lhs, C const& rhs) const
    {
        return lhs.text(info_n).length() < rhs.text(info_n).length();
    }
};

int get_max_width(std::vector<C> const& c_vec, C::Info::size_type info_n)
{
    std::vector<C>::const_iterator max = std::max_element(c_vec.cbegin(), c_vec.cend(),
        lambda_max(info_n));

    return max != c_vec.end() ? max->text(info_n).length() : 0;
}
  • 0
    Ваше решение хорошо подходит. Плюс: чем проще - тем лучше. Благодарю.
4

Здесь решение С++ 03, использующее Boost.Phoenix

#include <functional>
#include <boost/phoenix.hpp>

int get_max_width(std::vector<C> const& c_vec, C::Info::size_type info_n)
{
    namespace phx = boost::phoenix;
    using namespace phx::arg_names;

    std::vector<C>::const_iterator max = std::max_element(c_vec.begin(), c_vec.end(),
        phx::bind(std::mem_fun_ref(&std::string::length), phx::bind(&C::text, arg1, phx::val(info_n))) < 
        phx::bind(std::mem_fun_ref(&std::string::length), phx::bind(&C::text, arg2, phx::val(info_n)))
      );

    return max != c_vec.end() ? max->text(info_n).length() : 0;
}

Я не слишком много тестировал, но, похоже, здесь работает.

  • 0
    Я не могу использовать Феникс из-за ограничений проекта, но спасибо за подсказку.
  • 3
    Q: «Реализация с использованием boost» A: реализация с использованием boost OP: «Я не могу использовать Boost Phoenix». WAAAT?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню