全部用gcc 11.2和libstdc++-11完成。
下面的代码展示了使用std::sort和std::ranges::sort对内置、用户定义的类型和std库类型进行排序的各种方法。
只有std库类型给我带来麻烦:
operator<或operator<=>,因为将它添加到namespace std中是UB。我觉得没有办法可以绕过这一切吗?(不使用lambda或类似的)proj参数传递(但它可以在用户定义的类型上工作)。为什么?我无法洞穿“错误之墙”,无法找到答案。gcc基本上说:no known conversion for argument 3 from ‘<unresolved overloaded function type>’ to ‘std::identity’..更新:我上面关于2.的唯一理论是,“未解析的重载函数类型”意味着std::complex<double>::real有2个重载。一个接受参数( "setter"),另一个不接受参数( "getter")。是否有允许我指定没有参数的“地址”的语法?
Update2:感谢康桓瑋在评论中指出,无论如何,在std中获取成员函数的地址就是UB。但是,如果我将sum(int c)重载添加到thing (现在添加到下面),就会得到相同的“未解决的重载”错误。所以问题仍然是,我如何选择一个没有对角的。还是没有办法?
#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;
}发布于 2022-02-08 14:27:39
如果T不可用,则需要为std::less<T>指定一个比较。
std::sort和std::ranges::sort都需要严格的弱顺序谓词,而不是operator<=> (但可以通过<和std::less提供一个)。
template<typename T>
bool complex_less (std::complex<T> lhs, std::complex<T> rhs) { return abs(lhs) < abs(rhs); };
int main() {
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, {}, static_cast<int (thing::*)()>(&thing::sum)); // need cast to disambiguate pointer-to-member
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(), complex_less<double>); // fine
std::ranges::sort(complexes, complex_less<double>); // also fine
std::ranges::sort(complexes, {}, [](const auto& c) { return std::abs(c); }); // still fine
std::ranges::sort(complexes, {}, [](const auto& c) { return c.real(); }); // fine
for (const auto& e: complexes) std::cout << e << " ";
std::cout << "\n";
return EXIT_SUCCESS;
}https://stackoverflow.com/questions/71035326
复制相似问题