From 5ad6d25b7881d08823aea234fceddb55cd5aaf0a Mon Sep 17 00:00:00 2001 From: Valery Mironov Date: Sun, 29 Dec 2024 23:50:01 +0300 Subject: [PATCH 1/3] Make compatible with C++20 and C++26 --- absl/strings/charconv.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h index e5733f8c251..665135111cd 100644 --- a/absl/strings/charconv.h +++ b/absl/strings/charconv.h @@ -47,6 +47,10 @@ enum class chars_format { struct from_chars_result { const char* absl_nonnull ptr; std::errc ec; + + bool operator==(const from_chars_result&) = default; + + constexpr explicit operator bool() const noexcept { return ec == std::errc{}; } }; // Workalike compatibility version of std::from_chars from C++17. Currently From 68cd0fc38c1a68e3d04b007cb497c7a78b628854 Mon Sep 17 00:00:00 2001 From: mbkkt Date: Thu, 1 May 2025 06:14:57 +0000 Subject: [PATCH 2/3] Fix code --- absl/strings/charconv.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h index 665135111cd..f8abbfc2253 100644 --- a/absl/strings/charconv.h +++ b/absl/strings/charconv.h @@ -48,9 +48,14 @@ struct from_chars_result { const char* absl_nonnull ptr; std::errc ec; - bool operator==(const from_chars_result&) = default; + constexpr friend bool operator==(const from_chars_result& l, + const from_chars_result& r) noexcept { + return l.ptr == r.ptr && l.ec == r.ec; + } - constexpr explicit operator bool() const noexcept { return ec == std::errc{}; } + constexpr explicit operator bool() const noexcept { + return ec == std::errc{}; + } }; // Workalike compatibility version of std::from_chars from C++17. Currently From 7f683267671e710321860ecd02de41aa4a519d8b Mon Sep 17 00:00:00 2001 From: mbkkt Date: Thu, 1 May 2025 06:15:07 +0000 Subject: [PATCH 3/3] Add test --- absl/strings/charconv_test.cc | 113 ++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/absl/strings/charconv_test.cc b/absl/strings/charconv_test.cc index c16c735c24b..55a3f785efb 100644 --- a/absl/strings/charconv_test.cc +++ b/absl/strings/charconv_test.cc @@ -784,4 +784,117 @@ TEST(FromChars, DecimalFloatLimits) { TestOverflowAndUnderflow(input_gen, expected_gen, -45, 38); } +#if !defined(ABSL_INTERNAL_CPLUSPLUS_LANG) || \ + ABSL_INTERNAL_CPLUSPLUS_LANG < 202002L +constexpr bool operator!=(const absl::from_chars_result& l, + const absl::from_chars_result& r) noexcept { + return !(l == r); +} +#endif +// Check that the operator== for from_chars_result works as expected. +// +// EXPECT_TRUE and EXPECT_FALSE used intentionally to check operator== and +// operator!= explicitly. +// Before C++20 we need to define the operator!= explicitly, as it is not +// automatically generated by the compiler. +TEST(FromChars, ResultOperatorEqual) { + { + absl::from_chars_result result1{}; + absl::from_chars_result result2{}; + EXPECT_TRUE(result1 == result2); + EXPECT_FALSE(result1 != result2); + } + + { + absl::from_chars_result result1{}; + result1.ec = std::errc::result_out_of_range; + absl::from_chars_result result2{}; + result2.ec = std::errc::result_out_of_range; + EXPECT_TRUE(result1 == result2); + EXPECT_FALSE(result1 != result2); + } + { + absl::from_chars_result result1{}; + result1.ec = std::errc::result_out_of_range; + absl::from_chars_result result2{}; + EXPECT_FALSE(result1 == result2); + EXPECT_TRUE(result1 != result2); + } + { + absl::from_chars_result result1{}; + absl::from_chars_result result2{}; + result2.ec = std::errc::result_out_of_range; + EXPECT_FALSE(result1 == result2); + EXPECT_TRUE(result1 != result2); + } + + { + absl::from_chars_result result1{}; + result1.ptr = ""; + absl::from_chars_result result2{}; + result2.ptr = ""; + EXPECT_TRUE(result1 == result2); + EXPECT_FALSE(result1 != result2); + } + { + absl::from_chars_result result1{}; + result1.ptr = ""; + absl::from_chars_result result2{}; + EXPECT_FALSE(result1 == result2); + EXPECT_TRUE(result1 != result2); + } + { + absl::from_chars_result result1{}; + absl::from_chars_result result2{}; + result2.ptr = ""; + EXPECT_FALSE(result1 == result2); + EXPECT_TRUE(result1 != result2); + } + + { + absl::from_chars_result result1{"", std::errc::result_out_of_range}; + absl::from_chars_result result2{"", std::errc::result_out_of_range}; + EXPECT_TRUE(result1 == result2); + EXPECT_FALSE(result1 != result2); + } + { + absl::from_chars_result result1{"", std::errc::result_out_of_range}; + absl::from_chars_result result2{}; + EXPECT_FALSE(result1 == result2); + EXPECT_TRUE(result1 != result2); + } + { + absl::from_chars_result result1{}; + absl::from_chars_result result2{"", std::errc::result_out_of_range}; + EXPECT_FALSE(result1 == result2); + EXPECT_TRUE(result1 != result2); + } +} + +// Check that the operator bool for from_chars_result works as expected. +TEST(FromChars, ResultOperatorBool) { + { + absl::from_chars_result result{}; + EXPECT_TRUE(result); + EXPECT_FALSE(!result); + } + { + absl::from_chars_result result{}; + result.ec = std::errc::result_out_of_range; + EXPECT_FALSE(result); + EXPECT_TRUE(!result); + } + { + absl::from_chars_result result{}; + result.ptr = ""; + EXPECT_TRUE(result); + EXPECT_FALSE(!result); + } + { + absl::from_chars_result result{"", std::errc::result_out_of_range}; + EXPECT_FALSE(result); + EXPECT_TRUE(!result); + } +} + } // namespace