-
Notifications
You must be signed in to change notification settings - Fork 61
Description
On a Windows build using clang-cl, the build of //riegeli/records/record_reader fails with:
external/riegeli+/riegeli/records/record_reader.cc(651,9): error: call to 'BinarySearch' is ambiguous
651 | BinarySearch(
| ^~~~~~~~~~~~
external/riegeli+\riegeli/base/binary_search.h(375,26): note: candidate function [with Pos = unsigned long long, Test = (lambda at external/riegeli+/riegeli/records/record_reader.cc:653:13), $2 = 0]
375 | inline SearchResult<Pos> BinarySearch(Pos low, Pos high, Test&& test) {
| ^
external/riegeli+\riegeli/base/binary_search.h(454,41): note: candidate function [with Pos = unsigned long long, Test = (lambda at external/riegeli+/riegeli/records/record_reader.cc:653:13), $2 = 0]
454 | inline std::optional<SearchResult<Pos>> BinarySearch(Pos low, Pos high,
| ^
The call in question is here:
riegeli/riegeli/records/record_reader.cc
Line 651 in a5d3729
| BinarySearch( |
It has the signature:
BinarySearch(uint64_t, uint64_t, std::optional<PartialOrdering>(uint64_t record_index));
But the compiler thinks it matches the plain overload:
riegeli/riegeli/base/binary_search.h
Lines 370 to 375 in a5d3729
| template < | |
| typename Pos, typename Test, | |
| std::enable_if_t<binary_search_internal::TestReturnsOrderingOrSearchGuide< | |
| Test, Pos>::value, | |
| int>> | |
| inline SearchResult<Pos> BinarySearch(Pos low, Pos high, Test&& test) { |
As well as the std::optional one:
riegeli/riegeli/base/binary_search.h
Lines 449 to 455 in a5d3729
| template <typename Pos, typename Test, | |
| std::enable_if_t< | |
| binary_search_internal::TestReturnsOptionalOrderingOrSearchGuide< | |
| Test, Pos>::value, | |
| int>> | |
| inline std::optional<SearchResult<Pos>> BinarySearch(Pos low, Pos high, | |
| Test&& test) { |
It should match the latter, the test returns std::optional<PartialOrdering>, and that should match if PartialOrdering satisfies IsOrdering, which is defined as:
riegeli/riegeli/base/compare.h
Lines 67 to 74 in a5d3729
| template <typename T, typename Enable = void> | |
| struct IsOrdering : std::false_type {}; | |
| template <typename T> | |
| struct IsOrdering<T, std::void_t<decltype(std::declval<T>() < 0), | |
| decltype(std::declval<T>() > 0), | |
| decltype(std::declval<T>() == 0)>> | |
| : std::true_type {}; |
So it should match if all of <, >, and == are defined when the other arg is 0. But if that applies to T, shouldn't it also apply to std::optional<T>? It does seem like the way those comparison operators are derived differs in C++20, the other comparison operators for std::optional are derived from <=> starting in C++20. But I'm still very confused why the error is only coming up with clang-cl on Windows and not Clang on other platforms.