girona español descargar bonn c++ algorithm c++11 pointer-to-member

c++ - español - qgis girona



algoritmos estándar con puntero a miembro como comparador/"clave" (5)

¿Qué tal una vez que el operator< sobrecarga operator< para su tipo personalizado? Esto se puede hacer naturalmente dentro de la clase (o directamente junto a ella), y luego no se requieren argumentos adicionales al lado de los iteradores.

Pasar su función val() no es posible, ya que debe pasar un operador binario.

EDITAR: Habiendo leído las otras alternativas valiosas (también la buena respuesta de Sehe), quiero confirmar lo que ya mencioné en el comentario a continuación: En mi opinión, nada supera la legibilidad, la localidad y también la flexibilidad de una expresión lambda (- en el riesgo de escribir algunos pasajes dos veces).

@Ryan Haining: te sugiero que lo guardes como en tu publicación original.

A menudo me encuentro usando std::sort , std::max_element y similares con un lambda que simplemente invoca una función miembro

std::vector<MyType> vec; // populate... auto m = std::max_element(std::begin(vec), std::end(vec), [](const MyType& a, const MyType& b) { return a.val() < b.val()})

Esto se siente como un desperdicio de personajes y una pérdida de claridad. Soy consciente de que podría escribir otra función / llamable y pasar un indicador de función / objeto llamable a estas funciones de algoritmo, pero a menudo necesito hacer este tipo solo una vez en un programa y no me parece una buena opción. Manera de abordar el problema. Lo que quiero hacer, idealmente es decir:

auto m = std::max_element(std::begin(vec), std::end(vec), &MyType::val);

y tener los objetos ordenados por su val() s. ¿Hay alguna parte de la norma que estoy pasando por alto que pueda ayudarme con esto? u otra forma simple de hacerlo? Me gustaría hacer que lo que se está clasificando o buscando sea lo más obvio posible.

Soy consciente de que solo &MyType::val no es suficiente, estoy buscando algo que quizás pueda envolverlo, o proporcionar una funcionalidad similar sin entorpecer el significado.


Puede hacerlo without introducir ninguna función nueva (con o sin plantilla).

Just usa bind y std::less

auto m = std::max_element(vec.begin(), vec.end(), bind(less<>(), bind(&MyType::val, _1), bind(&MyType::val, _2)));


Puede usar std::mem_fn (o std::tr1::mem_fn )

int main() { std::vector<MyType> vec; auto m = std::max_element(std::begin(vec), std::end(vec), compare_by(std::mem_fn(&MyType::field))); }

Por supuesto, esto supone que tienes una utilidad como compare_by en tu caja de herramientas (como deberías :)):

template <typename F> struct CompareBy { explicit CompareBy(F&& f) : f(std::forward<F>(f)) {} template <typename U, typename V> bool operator()(U const& u, V const& v) const { return f(u) < f(v); } private: F f; }; template <typename F> CompareBy<F> compare_by(F&& f) { return CompareBy<F>(std::forward<F>(f)); }

Véalo en vivo en Coliru


Un comparador de plantillas podría ayudarte a:

template <typename StructureType, typename MemberType, MemberType StructureType::*member> bool comparator(const StructureType& the_first, const StructureType& the_second) { return the_first.*member < the_second.*member; }

http://ideone.com/K8ytav

Un poco de rasgos de tipo magia ciertamente podría permitirte evitar escribir el tipo.


Una mejora en la respuesta de la secuencia, para evitar la necesidad de usar std::mem_fn sería proporcionar un puntero a la sobrecarga de miembros para la función compare_by .

ejemplo de uso

std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field)); std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field, std::greater<>{}));

el código a implementar

#include <functional> // std::less #include <utility> // std::move #include <type_traits> // std::is_invocable_r // Forward declaration template<typename R, typename T, typename F = std::less<R>> auto compare_by(R T::*, F = F{}); // Implementation namespace detail { template<typename T, typename F> struct compare_by_t; template<typename R, typename T, typename F> struct compare_by_t<R T::*, F> : private F { compare_by_t(F&& f, R T::*m): F{std::move(f)}, _member{m} {} R T::* _member; bool operator()(T const& x, T const& y) const { return F::operator()(x .* _member, y .* _member); } }; } // detail template<typename R, typename T, typename F> auto compare_by(R T::* member, F f) { static_assert(std::is_invocable_r<bool, F, R, R>::value); return detail::compare_by_t<R T::*, F>{ std::move(f), member }; }