c++ implicit-conversion stl-algorithm c++17 c++-concepts

c++ - ¿Menos que operador a través de conversión implícita?



implicit-conversion stl-algorithm (3)

¿Se puede usar C en algoritmos estándar como std::sort que actualmente usa el operador < predeterminado?

Sí, funciona para std::sort() y algunos otros algoritmos estándar. El código

#include <algorithm> #include <vector> struct C { /* Class contents, without any arithmetic operator... */ constexpr operator int() noexcept {return 0;} // Implicit conversion to int }; int main() { std::vector<C> v; std::sort( begin(v), end(v) ); }

compila Aquí hay una demostración en vivo. ¡Mira la siguiente pregunta!

¿Se considera que C satisface el concepto LessThanComparable ?

No. Los requisitos del concepto LessThanComparable son que para los objetos y del tipo C o const C la expresión x<y es válida e implícitamente convertible a bool y el operador < establece una relación de ordenamiento estricto y débil. En su caso, los objetos const no se convertirán a int s. Este es un error en su código, porque no es correcto de const. Agregar la palabra clave const hará que funcione y la clase C sería LessThanComparable . Se cumple la estricta relación de ordenamiento débil, porque se cumple este requisito.

C cumplirá con los requisitos de una biblioteca de algoritmos conceptuales hipotéticos que requeriría que el tipo sea LessThanComparable .

Si arreglas tu constness, sí, lo hará.

Unas pocas notas al margen:

  • GCC 4.9 compila x<y incluso si x e y son de tipo const C Esto parece ser un error del compilador, ya que GCC 5.2 y el lenguaje 3.6 arrojan un error de compilación aquí.

  • Pasar std::less<C>() como un argumento adicional a std::sort() genera un error de tiempo de compilación, porque la función de comparación requiere que los objetos constantes sean comparables en ese caso. Sin embargo, pasar std::less<void>() no rompe nada, ya que los argumentos se envían perfectamente.

  • El algoritmo std::sort() no requiere un LessThanComparable completo, pero el concepto Compare . Además, el tipo de iterador debe ser un RandomAccessIterator que es ValueSwappable y el tipo de referencia no debe ser MoveContructable y MoveAssignable . Este es todo el caso para su primera pregunta, incluso cuando el error de constness no está resuelto. Es por eso que std::sort() y otros algoritmos estándar funcionan.

Considere la siguiente clase:

struct C { /* Class contents, without any arithmetic operator... */ constexpr operator int() noexcept; // Implicit conversion to int };

Mi pregunta es:

  • ¿Se puede usar C en algoritmos estándar como std::sort que actualmente usa el operador <predeterminado?
  • ¿Se considera que C satisface el concepto LessThanComparable ?
  • C cumplirá con los requisitos de una biblioteca de algoritmos conceptuales hipotéticos que requeriría que el tipo sea LessThanComparable .

No. El compilador no puede hacer tanta magia, es decir, llamar al método de conversión y luego aplicar el operador < . Imagine que hay varios operadores de cast para diferentes tipos, ¿cómo elegiría el compilador el adecuado?

EDIT: En realidad no es correcto. Mientras haya un solo operador de fundición, esto funcionará. Pero con dos o más, el compilador se quejará del reparto ambiguo. Sin embargo, este enfoque es muy frágil, por lo que en general no es una buena idea.


Probé el ejemplo propuesto por mehrdad momeny . Funcionó bien Sin embargo, con poca edición, ya no funciona.

#include <iostream> #include <string> #include <vector> #include <algorithm> struct C { C(int x):X(x){} operator int() { return X; } operator float() { return static_cast<float>(X); } int X; }; using namespace std; int main() { vector<C> u = {1, 2, 35, 6, 3, 7, 8, 9, 10}; sort(u.begin(), u.end()); for(auto x: u){ cout << x << endl; } }

Demo en vivo

Porque esto llevará a una ambigüedad. Por lo tanto, no es una buena idea hacerlo de esta manera.