diff --git a/riegeli/base/BUILD b/riegeli/base/BUILD index 3460cea2..b38edf91 100644 --- a/riegeli/base/BUILD +++ b/riegeli/base/BUILD @@ -429,6 +429,7 @@ cc_library( ":compare", ":estimated_allocated_size", ":new_aligned", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/hash", "@com_google_absl//absl/strings", diff --git a/riegeli/base/compact_string.cc b/riegeli/base/compact_string.cc index 8a62902d..d1eabbd8 100644 --- a/riegeli/base/compact_string.cc +++ b/riegeli/base/compact_string.cc @@ -14,6 +14,7 @@ #include "riegeli/base/compact_string.h" +#include // IWYU pragma: keep #include #include @@ -27,6 +28,15 @@ namespace riegeli { +// Before C++17 if a constexpr static data member is ODR-used, its definition at +// namespace scope is required. Since C++17 these definitions are deprecated: +// http://en.cppreference.com/w/cpp/language/static +#if !__cpp_inline_variables +constexpr uintptr_t CompactString::kDefaultRepr; +constexpr size_t CompactString::kInlineCapacity; +constexpr size_t CompactString::kInlineDataOffset; +#endif + void CompactString::AssignSlow(absl::string_view src) { const size_t old_capacity = capacity(); DeleteRepr(std::exchange( diff --git a/riegeli/base/compact_string.h b/riegeli/base/compact_string.h index 71d6a3ea..6e6f1de1 100644 --- a/riegeli/base/compact_string.h +++ b/riegeli/base/compact_string.h @@ -24,6 +24,7 @@ #include #include "absl/base/attributes.h" +#include "absl/base/config.h" #include "absl/base/optimization.h" #include "absl/hash/hash.h" #include "absl/strings/string_view.h" @@ -236,30 +237,25 @@ class static constexpr size_t kInlineCapacity = UnsignedMin(sizeof(uintptr_t) - 1, size_t{0xff >> 3}); - // For Little Endian, returns 1. - // For Big Endian, returns 0. - // - // TODO: Use `std::endian` instead when C++20 is available. - // - // With the following implementation the result is not known at preprocessing - // time nor during constexpr evaluation, but this function is in practice - // optimized out to a constant. - static size_t InlineDataOffset() { - const uintptr_t value = 1; - return size_t{reinterpret_cast(&value)[0]}; - } +#if ABSL_IS_LITTLE_ENDIAN + static constexpr size_t kInlineDataOffset = 1; +#elif ABSL_IS_BIG_ENDIAN + static constexpr size_t kInlineDataOffset = 0; +#else +#error Unknown endianness +#endif static char* inline_data(uintptr_t& repr) { RIEGELI_ASSERT_EQ(repr & 7, 1u) << "Failed precondition of CompactString::inline_data(): " "representation not inline"; - return reinterpret_cast(&repr) + InlineDataOffset(); + return reinterpret_cast(&repr) + kInlineDataOffset; } static const char* inline_data(const uintptr_t& repr) { RIEGELI_ASSERT_EQ(repr & 7, 1u) << "Failed precondition of CompactString::inline_data(): " "representation not inline"; - return reinterpret_cast(&repr) + InlineDataOffset(); + return reinterpret_cast(&repr) + kInlineDataOffset; } char* inline_data() { return inline_data(repr_); }