Change the `RiegeliHasMovableElements()` extension protocol to improve compatibility with MSVC. Instead of a constexpr function returning `bool`, it is a function retuning `std::true_type`, `std::false_type`, or `std::bool_constant<value>`. It is never called, only its result type is checked. PiperOrigin-RevId: 937164857
diff --git a/riegeli/base/iterable.h b/riegeli/base/iterable.h index 366ad60..f7adbb3 100644 --- a/riegeli/base/iterable.h +++ b/riegeli/base/iterable.h
@@ -77,6 +77,15 @@ decltype(size(std::declval<const Iterable&>())), size_t>>> : std::true_type {}; +template <typename Iterable, typename = void> +struct HasRiegeliHasMovableElements : std::false_type {}; + +template <typename Iterable> +struct HasRiegeliHasMovableElements< + Iterable, std::void_t<decltype(RiegeliHasMovableElements( + static_cast<Iterable* absl_nullable>(nullptr)))>> + : std::true_type {}; + } // namespace iterable_internal // `IsIterable<T>::value` is `true` when `T` is iterable, supporting @@ -102,12 +111,14 @@ // move would just yield unnecessarily separate template instantiations. // // To customize that for a class `Iterable`, define a free function -// `friend constexpr bool RiegeliHasMovableElements(Iterable*)` as a friend of -// `Iterable` inside class definition or in the same namespace as `Iterable`, -// so that it can be found via ADL. +// `friend T RiegeliHasMovableElements(Iterable*) { return {}; }` as a friend +// of `Iterable` inside class definition or in the same namespace as `Iterable`, +// so that it can be found via ADL. Its return type should have a static +// member `value`, such as `std::true_type`, `std::false_type`, or +// `std::bool_constant<value>`. // -// The argument of `RiegeliHasMovableElements(Iterable*)` is always a null -// pointer, used to choose the right overload based on the type. +// `RiegeliHasMovableElements(Iterable*)` is never called, only its result type +// is checked. template <typename Iterable, typename Enable = void> struct HasMovableElements @@ -118,14 +129,11 @@ template <typename Iterable> struct HasMovableElements< - Iterable, - std::enable_if_t<std::conjunction_v< - std::negation<std::is_reference<Iterable>>, - std::is_convertible<decltype(RiegeliHasMovableElements( - static_cast<Iterable* absl_nullable>(nullptr))), - bool>>>> - : std::bool_constant<RiegeliHasMovableElements( - static_cast<Iterable* absl_nullable>(nullptr))> {}; + Iterable, std::enable_if_t<std::conjunction_v< + std::negation<std::is_reference<Iterable>>, + iterable_internal::HasRiegeliHasMovableElements<Iterable>>>> + : decltype(RiegeliHasMovableElements( + static_cast<Iterable* absl_nullable>(nullptr))){}; template <typename Iterable> struct HasMovableElements<Iterable&> : std::false_type {};