-
Notifications
You must be signed in to change notification settings - Fork 1.5k
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
STL: expected<any, T>
and its friends can break container iterator comparison
#4847
Comments
I'm working on fixing this. BTW, I guess we should change all container iterators to something like |
expected<any, T>>
and its friends can break container iterator comparisonexpected<any, T>
and its friends can break container iterator comparison
This program shows that all standard library implementations are currently buggy. Godbolt link. #include <cstddef>
#include <vector>
#include <array>
#include <deque>
struct any_convertible_subtractable {
any_convertible_subtractable() = default;
template<class T>
any_convertible_subtractable(T&&) {}
template<class T>
friend std::ptrdiff_t operator-(any_convertible_subtractable, T&&)
{
return 0;
}
template<class T>
friend std::ptrdiff_t operator-(T&&, any_convertible_subtractable)
{
return 0;
}
};
template<class Cont>
void test_container(Cont&& c)
{
(void)(c.end() - c.begin());
}
int main()
{
test_container(std::vector<any_convertible_subtractable>{});
test_container(std::array<any_convertible_subtractable, 1>{});
test_container(std::deque<any_convertible_subtractable>{});
} Edit: NOT SURE whether the issue with forwarding references can be fixed. |
I just found my way here after a day banging my head against the table/reproducing cut-down versions of STL concept checks, trying to comprehend why MSVC was telling me my It would seem very unfortunate (not to mention unexpected!) for there to be such an arbitrary exclusion of certain types from being usable with STL containers. Regarding your comment in the linked PR, I can say that for sure usage of I'm also a little curious as to why |
If you have a wrapper struct where the
Yeah, that's a good question, it's not obvious to me from a brief glance. Someone (possibly me, later; busy now) should figure out the root cause of the difference, and then it might be possible to raise an LWG issue. |
Thank you! I've tagged the point in my code so if at any point you could use some more info or want an additional test case, feel free to ping me here. |
Bit of a hack that fixes only template <class _Uty>
+ requires (!same_as<any, _Ty>)
_NODISCARD friend constexpr bool operator==(const expected& _Left, const _Uty& _Right) noexcept(
noexcept(static_cast<bool>(_Left._Value == _Right))) /* strengthened */ { This may be "good enough" to tide us over until we can completely rework our iterators to avoid having The problem is that e.g. Note that we can't simply constrain this EDIT: "For which this same overload is viable" in the above seems questionable. We were looking at |
Interesting. I guess this is just predicated on the knowledge that Seems like a nightmare generally though, I really wonder why |
It's still a bit iffy since a user could (please don't) create a type that defines equality with
WG21 really wanted |
For posterity, my reduced repro: struct any {
template <class U> any(U&&);
};
template <class T> struct expected {
template <class U> expected(U&&);
template <class U>
requires requires(const T& t, const U& u) { t == u; } // line 9
friend bool operator==(const expected&, const U&) { return true; }
};
template <class> struct const_iterator {
bool operator==(const const_iterator&) const = default;
};
template <class T> struct iterator : const_iterator<T> {};
int main() {
using I = iterator<expected<any>>;
return I{} == I{};
} MSVC is happy with the workaround constraint I've added on line 9. Clang and GCC say the program has constraint recursion (https://godbolt.org/z/PMh4rdbYe). I (and apparently MSVC) believe that |
Describe the bug
The bug reported in GCC Bugzilla #115939 is currently also present in MSVC STL. Iterator comparison is currently broken for all but set containers.
The reason of the bug is that
expected<any, T>
is so permissive on implicit conversion thatoperator==
forexpected
can cause ambiguity. Note that while there may be a defect inexpected
, such ambiguity can also caused by some (misdesigned) user-defined types in C++14 mode.Command-line test case
Godbolt link
Expected behavior
This program compiles and
operator==
overloads for iterators are selected.STL version
Microsoft Visual Studio Community 2022
Version 17.11.0 Preview ? (14.41.33923 from Godbolt)
Still present in 17.11.0 Preview 4.0 and ecbc1ef.
Additional context
The text was updated successfully, but these errors were encountered: