-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compare operator not defined for recursive data types on C++20 #67056
Comments
Implementations on consistent on rejecting this for C++20: https://godbolt.org/z/n9a9rqvhf and consistent on accepting it or C++17: https://godbolt.org/z/TEosMb6e5 So, that indicates it is likely purposeful but I have to dig some more to understand why. CC @erichkeane |
So it looks like the problem is this expression: https://godbolt.org/z/x9svWvTPv decltype(std::declval<std::vector<DT>>() < std::declval<std::vector<DT>>()); If we change the code like this: https://godbolt.org/z/9hccvdTes template <typename T1, typename T2>
static auto hasLessThanHelper(int)
//-> decltype(std::declval<T1>() < std::declval<T2>(), std::true_type{});
-> std::true_type; it stops failing. It looks like during synthesizing the spaceship operator it ends up in a recursion and fails. |
Yeah, looks like it. But I don't expect this to be a recursion because in the |
@llvm/issue-subscribers-c-20
Cross-posting https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111504
The following code works on C++17 but not C++20: #include <cstdint>
#include <type_traits>
#include <vector>
template <typename T1, typename T2>
static auto hasLessThanHelper(int)
-> decltype(std::declval<T1>() < std::declval<T2>(), std::true_type{});
template <typename, typename>
static auto hasLessThanHelper(long) -> std::false_type;
template <typename T1, typename T2>
struct hasLessThan : decltype(hasLessThanHelper<T1, T2>(0)) {};
struct DynamicType {
using T1 = int64_t;
using T2 = std::vector<DynamicType>;
};
template <
typename DT,
typename = std::enable_if_t<
(hasLessThan<typename DT::T1, typename DT::T1>::value ||
hasLessThan<typename DT::T1, typename DT::T2>::value ||
hasLessThan<typename DT::T2, typename DT::T1>::value ||
hasLessThan<typename DT::T2, typename DT::T2>::value)>>
inline constexpr bool operator<(const DT& x, const DT& y) {
// implementation omitted
return true;
}
int main() {
using DT = DynamicType;
// This assert works on C++17, but fails on C++20
static_assert(hasLessThan<std::vector<DT>, std::vector<DT>>::value);
} |
@llvm/issue-subscribers-clang-frontend
Cross-posting https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111504
The following code works on C++17 but not C++20: #include <cstdint>
#include <type_traits>
#include <vector>
template <typename T1, typename T2>
static auto hasLessThanHelper(int)
-> decltype(std::declval<T1>() < std::declval<T2>(), std::true_type{});
template <typename, typename>
static auto hasLessThanHelper(long) -> std::false_type;
template <typename T1, typename T2>
struct hasLessThan : decltype(hasLessThanHelper<T1, T2>(0)) {};
struct DynamicType {
using T1 = int64_t;
using T2 = std::vector<DynamicType>;
};
template <
typename DT,
typename = std::enable_if_t<
(hasLessThan<typename DT::T1, typename DT::T1>::value ||
hasLessThan<typename DT::T1, typename DT::T2>::value ||
hasLessThan<typename DT::T2, typename DT::T1>::value ||
hasLessThan<typename DT::T2, typename DT::T2>::value)>>
inline constexpr bool operator<(const DT& x, const DT& y) {
// implementation omitted
return true;
}
int main() {
using DT = DynamicType;
// This assert works on C++17, but fails on C++20
static_assert(hasLessThan<std::vector<DT>, std::vector<DT>>::value);
} |
Cross-posting https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111504
The following code works on C++17 but not C++20:
The text was updated successfully, but these errors were encountered: