Подтвердить что ты не робот

Замена для binary_function

binary_function теперь устарела и будет удалена в С++ 17. Я искал в разных публикациях, но я не мог найти точного способа его замены. Я хотел бы знать, как написать следующий код в стиле С++ 11.

template <class T>
inline T absolute(const T &x) {
    return (x >= 0) ? x : -x;
}

template <class T>
struct absoluteLess : public std::binary_function<T, T, bool> {
    bool operator()(const T &x, const T &y) const {
        return absolute(x) < absolute(y);
    }
};

template <class T>
struct absoluteGreater : public std::binary_function<T, T, bool> {
    bool operator()(T &x, T &y) const {
        return absolute(x) > absolute(y);
    }
};

EDIT: Я использую функции следующим образом:

output[j] = *std::max_element(input.begin() + prev, input.begin() + pos, absoluteLess<float>());

вход и выход являются векторами, внутри цикла for

4b9b3361

Ответ 1

Во-первых, мой совет - смотреть CppCon 2015: Стефан Т. Лававей "Функционал: что нового и правильное использование" . std::binary_function упоминается на слайде 36, примерно на 36 минут в видео. Вы можете найти слайды в github.com/CppCon/CppCon2015). Не стоит вдаваться в подробности, почему вы не должны использовать std::binary_function, но если вы используете то, что было устарело с С++ 11, вам, вероятно, будет полезно наблюдать за ним.

Если вы хотите фактическое обоснование не использовать его, попробуйте n4190:

unary_function/binary_function были полезными помощниками, когда С++ 98-эра адаптерам нужен параметр argument_type/etc. Определения типов. Такие typedefs ненужное заданное С++ 11 совершенная пересылка, decltype и т.д. (И они неприменимы для перегрузки/шаблона вызова функции операторов.) Даже если класс хочет предоставить эти typedefs для обратной совместимости, он может сделать это напрямую (при незначительных затратах в многословие) вместо наследования от unary_function/binary_function, это то, что сам Стандарт начал делать, когда эти помощники устарели.

Теперь вам это просто не нужно, поэтому вы можете удалить все его следы из своей программы.

В С++ 14 были добавлены прозрачные компараторы. Но он может быть реализован в С++ 11. Просто выделите его для void:

template<>
struct absoluteLess<void> {
    template< class T, class U>
    constexpr auto operator()( T&& lhs, U&& rhs ) const
      -> decltype(absolute(std::forward<T>(lhs)) < absolute(std::forward<U>(rhs)))
    {
        return absolute(std::forward<T>(lhs)) < absolute(std::forward<U>(rhs));
    }
}
};

Теперь тип можно вывести:

std::max_element(v.begin(), v.end(), absoluteLess<>());

Ответ 2

Единственное, что делает std::binary_function, это предоставление членов typedefs result_type, first_argument_type и second_argument_type. И единственное, что используется в стандартной библиотеке, использующей эти typedefs, - это std::not2, которая 1) строго заменяется на С++ 17 std::not_fn, 2) легко заменяется лямбдой в любом случае и 3) устарел на С++ 17 и, вероятно, будет удален в следующей версии.

Если по какой-либо причине вам нужно использовать not2, устаревшие связующие (bind1st/bind2nd, обе устаревшие в С++ 11 и удаленные в С++ 17), или некоторые древние трек- после этого протокола, замена заключается в определении typedefs непосредственно в вашем классе:

using result_type = bool;
using first_argument_type = T;
using second_argument_type = T;

В противном случае просто удалите наследование.