es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Ordenación paralela con std::sort y un iterador personalizado convierte valores

Estoy escribiendo un método de ordenamiento que ordena dos arreglos simultáneamente, basado en los valores de uno de los arreglos. Usé esto como referencia y hice algunos cambios menores (hice que el operador *() sea constante y agregué constructores para la clase ref), por lo que compila en MSVC/g++/clang.

Después de agregar std::execution::par para habilitar la ordenación paralela, clang y g++ ya no lo compilan (pero MSVC sí). El código final y el error se pueden encontrar aquí. Los errores en g++ y clang son similares:

source:45:6: note: candidate function not viable: no known conversion from ‘const val’ to ‘const ref’ for 1st argument
bool operator<(ref const& a, val const& b)

Este error se puede resolver implementando bool operator<(val const& a, val const& b), pero luego el arreglo de valores finales retiene cadenas vacías. Esto se puede solucionar eliminando el operador move de operator val() &&. Sin embargo, el operador move fue una importante decisión de diseño para el rendimiento.

Pregunta: ¿Hay alguna manera de mantener el operador move?

Ahora compila en el entorno en línea de godbolt.org, pero no localmente, porque la instalación de tbb afecta los pasos de compilación. Tbb está instalado localmente y es necesario para la ejecución paralela real. El error es:

/usr/include/c++/9/pstl/parallel_backend_tbb.h:435:1: required from here
/usr/include/c++/9/bits/predefined_ops.h:215:11: error: no match for call to ‘(std::less) (const ref&, ref)’
215 | { return bool(_M_comp(__val, *__it)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/string:48,
from tmp.cpp:2:
/usr/include/c++/9/bits/stl_function.h:385:7: note: candidate: ‘constexpr bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = val]’
385 | operator()(const _Tp& __x, const _Tp& __y) const
| ^~~~~~~~
/usr/include/c++/9/bits/stl_function.h:385:7: note: conversion of argument 1 would be ill-formed:
In file included from /usr/include/c++/9/bits/stl_algobase.h:71,
from /usr/include/c++/9/vector:60,
from tmp.cpp:1:
/usr/include/c++/9/bits/predefined_ops.h:215:11: error: invalid user-defined conversion from ‘const ref’ to ‘const val&’ [-fpermissive]
215 | { return bool(_M_comp(__val, *__it)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
tmp.cpp:42:2: note: candidate is: ‘ref::operator val() &&’
42 | operator val() && { return {*key, *value}; }
| ^~~~~~~~
tmp.cpp:42:2: note: passing ‘const ref’ as ‘this’ argument discards qualifiers

Pregunta adicional: ¿Por qué quiere hacer una conversión si puede usar bool operator<(ref const& a, ref const& b)?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Como experto en IT especializado en C++, específicamente en C++17, puedo brindar la siguiente respuesta:

    Para mantener el operador de traslado, es necesario implementar bool operator<(val const& a, ref const& b). Esto permitirá la comparación del tipo de valor val con el tipo de referencia ref. La razón por la que el operador move estaba causando cadenas vacías en el array de valores finales es porque el operador move estaba transfiriendo la propiedad de la cadena, dejando el objeto original vacío.

    En cuanto a la pregunta complementaria, el error se produce porque el operator< que se llama espera un objeto val como primer argumento en lugar de un objeto ref. El error de conversión se produce porque no hay una conversión válida de const ref a const val& para el primer argumento. Si bien hay una implementación de bool operator<(ref const& a, ref const& b) disponible, no se puede utilizar en este caso porque el primer argumento esperado por el operador de comparación es const val&.

Comments are closed.