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 comostd::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 conceptoLessThanComparable
?
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 seaLessThanComparable
.
Si arreglas tu constness, sí, lo hará.
Unas pocas notas al margen:
GCC 4.9 compila
x<y
incluso six
ey
son de tipoconst 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 astd::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, pasarstd::less<void>()
no rompe nada, ya que los argumentos se envían perfectamente.El algoritmo
std::sort()
no requiere unLessThanComparable
completo, pero el conceptoCompare
. Además, el tipo de iterador debe ser unRandomAccessIterator
que esValueSwappable
y el tipo de referencia no debe serMoveContructable
yMoveAssignable
. Este es todo el caso para su primera pregunta, incluso cuando el error de constness no está resuelto. Es por eso questd::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;
}
}
Porque esto llevará a una ambigüedad. Por lo tanto, no es una buena idea hacerlo de esta manera.