Le tout avec gcc 11.2 et libstdc++-11
Le code ci-dessous montre différentes façons d'utiliser std::sort
y luego std::ranges::sort
pour trier les types intégrés, les types définis par l'utilisateur et un type de bibliothèque standard.
Seul le type de bibliothèque std me pose problème :
- Je ne peux pas facilement définir un
operator<
ooperator<=>
car c'est l'UB qui l'ajoute ànamespace std
. Je pense qu'il n'y a aucun moyen de contourner ce problème ? (sans utiliser un lambda ou similaire) - pour une raison quelconque, je ne peux pas passer une fonction membre publique en tant que fonction
proj
sur le type std lib (mais il fonctionne sur le type défini par l'utilisateur). Pourquoi ? Je n'ai pas réussi à pénétrer suffisamment le "mur d'erreurs" pour le découvrir. gcc dit en gros :no known conversion for argument 3 from ‘<unresolved overloaded function type>’ to ‘std::identity’
..
Mise à jour : Ma seule théorie sur le point 2 ci-dessus est que "type de fonction surchargée non résolue" signifie que std::complex<double>::real
a 2 surcharges. L'une prend un paramètre (le "setter") et l'autre n'en prend pas (le "getter"). Existe-t-il une syntaxe qui me permette de spécifier que je veux l'"adresse de" celle qui ne prend pas de paramètre ?
Mise à jour2 : Merci d'avoir signalé dans les commentaires que le fait de prendre l'adresse d'une fonction membre en std
n'est de toute façon que de l'UB. Cependant, si j'ajoute un sum(int c)
surcharge à thing
(ajouté ci-dessous), j'obtiens la même erreur "unresolved overloaded". La question reste donc de savoir comment sélectionner celui qui n'a pas de paramètres. Ou n'y a-t-il aucun moyen ?
#include <algorithm>
#include <compare>
#include <complex>
#include <iostream>
#include <ranges>
#include <vector>
namespace std {
// this is UNDEFINED BEHAVIOUR!!! --- but "it works", so we know this option is what would be
// required, but is not available to us
std::partial_ordering operator<=>(const std::complex<double>& a, const std::complex<double>& b) {
return std::abs(a) <=> std::abs(b);
}
} // namespace std
// a user defined type
struct thing {
int x{};
int y{};
[[nodiscard]] int sum() const { return x + y; }
[[nodiscard]] int sum(int c) const { return x + y + c; } // added for update 2
friend std::strong_ordering operator<=>(const thing& a, const thing& b) {
return a.x + a.y <=> b.x + b.y;
}
friend bool operator==(const thing& a, const thing& b) { return a.x + a.y == b.x + b.y; }
friend std::ostream& operator<<(std::ostream& os, const thing& rhs) {
return os << "[" << rhs.x << "," << rhs.y << "]";
}
};
int main() {
// builtin types
auto ints = std::vector<int>{9, 10, 7, 8, 5, 6, 3, 4, 1, 2};
std::ranges::sort(ints);
std::ranges::sort(ints, {}, [](const auto& c) { return -c; });
for (const auto& e: ints) std::cout << e << " ";
std::cout << "\n";
auto things = std::vector<thing>{{9, 10}, {7, 8}, {3, 4}, {1, 2}, {5, 6}};
std::sort(things.begin(), things.end());
std::ranges::sort(things);
std::ranges::sort(things, {}, [](const auto& e) { return e.sum(); });
std::ranges::sort(things, [](const auto& a, const auto& b) { return a < b; }, {});
std::ranges::sort(things, {}, &thing::x);
std::ranges::sort(things, {}, &thing::sum); // COMPILE ERROR afte r update 2
for (const auto& e: things) std::cout << e << " ";
std::cout << "\n";
auto complexes = std::vector<std::complex<double>>{{9, 10}, {7, 8}, {3, 4}, {1, 2}, {5, 6}};
std::sort(complexes.begin(), complexes.end()); // requires operator< or <=> which is UB
std::ranges::sort(complexes); // requires operator<=> which is UB
std::ranges::sort(complexes, {}, [](const auto& c) { return std::abs(c); });
std::ranges::sort(complexes, {}, &std::complex<double>::real); // COMPILE ERROR!!
for (const auto& e: complexes) std::cout << e << " ";
std::cout << "\n";
return EXIT_SUCCESS;
}