[libc++] Fix std::variant comparators not working on recursive instantiations (#182238)
We currently have an instantiation cycle in `variant`'s comparison operators. This patch fixes that by replacing a `decltype(auto)` with an explicit return type, removing the requirement to instantiate the function in order to know the return type. Fixes #182232
This commit is contained in:
@@ -614,7 +614,8 @@ private:
|
||||
template <class _Visitor>
|
||||
struct __value_visitor {
|
||||
template <class... _Alts>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Alts&&... __alts) const {
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Alts&&... __alts) const
|
||||
-> invoke_result_t<_Visitor&&, decltype((std::forward<_Alts>(__alts).__value))...> {
|
||||
__std_visit_exhaustive_visitor_check< _Visitor, decltype((std::forward<_Alts>(__alts).__value))...>();
|
||||
return std::__invoke(std::forward<_Visitor>(__visitor), std::forward<_Alts>(__alts).__value...);
|
||||
}
|
||||
|
||||
@@ -317,6 +317,72 @@ void test_relational() {
|
||||
#endif
|
||||
}
|
||||
|
||||
struct A1 {
|
||||
bool operator==(const A1&) const { return true; }
|
||||
bool operator!=(const A1&) const { return true; }
|
||||
bool operator<(const A1&) const { return true; }
|
||||
bool operator>(const A1&) const { return true; }
|
||||
bool operator<=(const A1&) const { return true; }
|
||||
bool operator>=(const A1&) const { return true; }
|
||||
};
|
||||
struct A2 {
|
||||
bool operator==(const A2&) const { return true; }
|
||||
bool operator!=(const A2&) const { return true; }
|
||||
bool operator<(const A2&) const { return true; }
|
||||
bool operator>(const A2&) const { return true; }
|
||||
bool operator<=(const A2&) const { return true; }
|
||||
bool operator>=(const A2&) const { return true; }
|
||||
};
|
||||
|
||||
struct Array;
|
||||
|
||||
using Var1 = std::variant<A1, Array>;
|
||||
using Var2 = std::variant<A2, Array>;
|
||||
|
||||
struct Array {
|
||||
Var1* ptr;
|
||||
|
||||
template <class Other>
|
||||
friend constexpr bool operator==(const Array& lhs, const Other& rhs) {
|
||||
return *lhs.ptr == *rhs.ptr;
|
||||
}
|
||||
|
||||
template <class Other>
|
||||
friend constexpr bool operator!=(const Array& lhs, const Other& rhs) {
|
||||
return *lhs.ptr != *rhs.ptr;
|
||||
}
|
||||
|
||||
template <class Other>
|
||||
friend constexpr bool operator<(const Array& lhs, const Other& rhs) {
|
||||
return *lhs.ptr < *rhs.ptr;
|
||||
}
|
||||
|
||||
template <class Other>
|
||||
friend constexpr bool operator>(const Array& lhs, const Other& rhs) {
|
||||
return *lhs.ptr > *rhs.ptr;
|
||||
}
|
||||
|
||||
template <class Other>
|
||||
friend constexpr bool operator<=(const Array& lhs, const Other& rhs) {
|
||||
return *lhs.ptr <= *rhs.ptr;
|
||||
}
|
||||
|
||||
template <class Other>
|
||||
friend constexpr bool operator>=(const Array& lhs, const Other& rhs) {
|
||||
return *lhs.ptr >= *rhs.ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// See https://llvm.org/PR182232
|
||||
void test_recursive() {
|
||||
(void)(Var2{} == Var2{});
|
||||
(void)(Var2{} != Var2{});
|
||||
(void)(Var2{} < Var2{});
|
||||
(void)(Var2{} > Var2{});
|
||||
(void)(Var2{} <= Var2{});
|
||||
(void)(Var2{} >= Var2{});
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test_equality();
|
||||
test_relational();
|
||||
|
||||
Reference in New Issue
Block a user