From b160feaac26bd63309da3e93b44832976493a385 Mon Sep 17 00:00:00 2001 From: Fredrik Roubert Date: Wed, 11 Sep 2024 15:59:23 +0200 Subject: [PATCH] ICU-22879 Provide collator based predicates for use with STL algorithms. --- docs/userguide/collation/api.md | 48 ++++++ icu4c/source/i18n/unicode/coll.h | 93 +++++++++++ icu4c/source/i18n/unicode/ucol.h | 124 +++++++++++++++ icu4c/source/test/intltest/collationtest.cpp | 155 +++++++++++++++++++ 4 files changed, 420 insertions(+) diff --git a/docs/userguide/collation/api.md b/docs/userguide/collation/api.md index c92dcf447bd..f7d0810e6ef 100644 --- a/docs/userguide/collation/api.md +++ b/docs/userguide/collation/api.md @@ -196,6 +196,12 @@ value, such as `ucol_greater`, `ucol_greaterOrEqual`, `ucol_equal` (in C) `Collator::greater`, `Collator::greaterOrEqual`, `Collator::equal` (in C++) and `Collator.equals` (in Java). +As of ICU 76 there are also C++ convenience functions and templates to create +standard library compliant comparison function objects that use a collator to +perform comparisons (instead of using the comparison operators on the strings +being compared), such as `Collator::less()` for a C++ API `Collator` or +`collator::less()` for a C API `UCollator`. + ### Examples **C:** @@ -238,6 +244,48 @@ delete coll; } ``` +**C++:** (as of ICU 76) + +```c++ +icu::ErrorCode status; +icu::Locale locale = icu::Locale::forLanguageTag("sv", status); +icu::LocalPointer collator(icu::Collator::createInstance(locale, status), status); +status.assertSuccess(); // Override ErrorCode::handleFailure() to handle failure. + +std::vector utf8{ + "Arnold", "Øystein", "Ingrid", "Åke", "Olof", "İsmail", "Örjan", +}; + +std::sort(utf8.begin(), utf8.end(), collator->less()); + +std::vector utf16{ + u"Arnold", u"Øystein", u"Ingrid", u"Åke", u"Olof", u"İsmail", u"Örjan", +}; + +std::sort(utf16.begin(), utf16.end(), collator->less()); +``` + +**C++:** (calling the ICU C API, as of ICU 76) + +```c++ +UErrorCode status = U_ZERO_ERROR; +icu::LocalUCollatorPointer ucollator(ucol_open("sv", &status)); +assert(U_SUCCESS(status)); +assert(ucollator.isValid()); + +std::vector utf8{ + "Arnold", "Øystein", "Ingrid", "Åke", "Olof", "İsmail", "Örjan", +}; + +std::sort(utf8.begin(), utf8.end(), icu::header::collator::less(ucollator.getAlias())); + +std::vector utf16{ + u"Arnold", u"Øystein", u"Ingrid", u"Åke", u"Olof", u"İsmail", u"Örjan", +}; + +std::sort(utf16.begin(), utf16.end(), icu::header::collator::less(ucollator.getAlias())); +``` + **Java:** ```java diff --git a/icu4c/source/i18n/unicode/coll.h b/icu4c/source/i18n/unicode/coll.h index 4845e8f02cc..2de467c4f07 100644 --- a/icu4c/source/i18n/unicode/coll.h +++ b/icu4c/source/i18n/unicode/coll.h @@ -58,12 +58,18 @@ #if !UCONFIG_NO_COLLATION +#include +#include +#include + +#include "unicode/char16ptr.h" #include "unicode/uobject.h" #include "unicode/ucol.h" #include "unicode/unorm.h" #include "unicode/locid.h" #include "unicode/uniset.h" #include "unicode/umisc.h" +#include "unicode/unistr.h" #include "unicode/uiter.h" #include "unicode/stringpiece.h" @@ -588,6 +594,52 @@ public: */ UBool equals(const UnicodeString& source, const UnicodeString& target) const; +#ifndef U_HIDE_DRAFT_API + + /** + * Creates a comparison function object that uses this collator. + * Like std::equal_to but uses the collator instead of operator==. + * @draft ICU 76 + */ + inline auto equal_to() const { return Predicate(*this); } + + /** + * Creates a comparison function object that uses this collator. + * Like std::greater but uses the collator instead of operator>. + * @draft ICU 76 + */ + inline auto greater() const { return Predicate(*this); } + + /** + * Creates a comparison function object that uses this collator. + * Like std::less but uses the collator instead of operator<. + * @draft ICU 76 + */ + inline auto less() const { return Predicate(*this); } + + /** + * Creates a comparison function object that uses this collator. + * Like std::not_equal_to but uses the collator instead of operator!=. + * @draft ICU 76 + */ + inline auto not_equal_to() const { return Predicate(*this); } + + /** + * Creates a comparison function object that uses this collator. + * Like std::greater_equal but uses the collator instead of operator>=. + * @draft ICU 76 + */ + inline auto greater_equal() const { return Predicate(*this); } + + /** + * Creates a comparison function object that uses this collator. + * Like std::less_equal but uses the collator instead of operator<=. + * @draft ICU 76 + */ + inline auto less_equal() const { return Predicate(*this); } + +#endif // U_HIDE_DRAFT_API + #ifndef U_FORCE_HIDE_DEPRECATED_API /** * Determines the minimum strength that will be used in comparison or @@ -1210,6 +1262,47 @@ private: friend class ICUCollatorService; static Collator* makeInstance(const Locale& desiredLocale, UErrorCode& status); + +#ifndef U_HIDE_DRAFT_API + /** + * Function object for performing comparisons using a Collator. + * @internal + */ + template