public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/109738] New: C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator
@ 2023-05-04 15:48 szhong at perforce dot com
2023-05-04 18:15 ` [Bug c++/109738] " pinskia at gcc dot gnu.org
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: szhong at perforce dot com @ 2023-05-04 15:48 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109738
Bug ID: 109738
Summary: C++20 implicit conversion is used during spaceship
operator resolution instead of class's operator< for
classes without spaceship operator
Product: gcc
Version: 11.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: szhong at perforce dot com
Target Milestone: ---
Using -std=c++20 -- implicit conversion is used during spaceship operator
resolution instead of class's operator< for classes without spaceship operator
testcase:
#include <string>
#include <list>
#include <map>
#include <iostream>
class StringWrapper {
public:
StringWrapper(const char* s)
: str_(s) {}
std::string str_;
operator const char* () const;
};
inline
StringWrapper::operator const char* () const
{
return str_.data();
}
std::ostream&
operator<<(std::ostream& os, const StringWrapper& str)
{
os << str.str_;
return os;
}
bool
operator< (const StringWrapper& lhs, const StringWrapper& rhs)
{
return lhs.str_ < rhs.str_;
}
#if defined(SPACE_SHIP)
auto operator<=>(const StringWrapper& lhs, const StringWrapper& rhs)
{
return lhs.str_ <=> rhs.str_;
}
#endif
void print_map(std::string_view comment, const
std::map<std::list<StringWrapper>, std::list<StringWrapper> >& m)
{
std::cout << comment;
// iterate using C++17 facilities
for (const auto& [key, value] : m) {
std::cout << '[';
for (const auto& i : key)
std::cout << i << ", ";
std::cout << "];";
}
std::cout << '\n';
}
int main()
{
StringWrapper a("Diane");
StringWrapper b("Harry");
StringWrapper c("Sally");
StringWrapper d("George");
std::list<StringWrapper> l1;
l1.push_back(a);
l1.push_back(c);
std::list<StringWrapper> l2;
l2.push_back(b);
l2.push_back(d);
std::map<std::list<StringWrapper>, std::list<StringWrapper> > m1;
m1.insert(m1.end(), std::map<std::list<StringWrapper>,
std::list<StringWrapper> >::value_type(l1, l2));
m1.insert(m1.end(), std::map<std::list<StringWrapper>,
std::list<StringWrapper> >::value_type(l2, l1));
print_map("m1: ", m1);
std::map<std::list<StringWrapper>, std::list<StringWrapper> > m2;
m2.insert(m2.end(), std::map<std::list<StringWrapper>,
std::list<StringWrapper> >::value_type(l2, l1));
m2.insert(m2.end(), std::map<std::list<StringWrapper>,
std::list<StringWrapper> >::value_type(l1, l2));
print_map("m2: ", m2);
}
$ g++ -std=c++20 -Wall -Wextra 20_list_compare_wrapper.cpp; ./a.out;
m1: [Harry, George, ];[Diane, Sally, ];
m2: [Diane, Sally, ];[Harry, George, ];
The problem is the std:map is no longer sorted according to StringWrapper but
sorted according const char* instead.
The debugger showed during resolution of spaceship operator, the implicit
conversion to const char* for StringWrapper is selected instead of
StringWrapper::operator<() during insertion into std::map with the key of
std::list<StringWrapper>.
This problem occurs with gcc 12.1.1 as well.
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
11.3.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs
--enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr
--with-gcc-major-version-only --program-suffix=-11
--program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object
--disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib
--enable-libphobos-checking=release --with-target-system-zlib=auto
--enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet
--with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32
--enable-multilib --with-tune=generic
--enable-offload-targets=nvptx-none=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-xKiWfi/gcc-11-11.3.0/debian/tmp-gcn/usr
--without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
--with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)
system type: $ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Bug c++/109738] C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator
2023-05-04 15:48 [Bug c++/109738] New: C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator szhong at perforce dot com
@ 2023-05-04 18:15 ` pinskia at gcc dot gnu.org
2023-05-10 20:52 ` redi at gcc dot gnu.org
2023-05-11 19:32 ` szhong at perforce dot com
2 siblings, 0 replies; 4+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-04 18:15 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109738
--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
clang has the same behavior as GCC .
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Bug c++/109738] C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator
2023-05-04 15:48 [Bug c++/109738] New: C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator szhong at perforce dot com
2023-05-04 18:15 ` [Bug c++/109738] " pinskia at gcc dot gnu.org
@ 2023-05-10 20:52 ` redi at gcc dot gnu.org
2023-05-11 19:32 ` szhong at perforce dot com
2 siblings, 0 replies; 4+ messages in thread
From: redi at gcc dot gnu.org @ 2023-05-10 20:52 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109738
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Scott Zhong from comment #0)
> The debugger showed during resolution of spaceship operator, the implicit
> conversion to const char* for StringWrapper is selected instead of
> StringWrapper::operator<() during insertion into std::map with the key of
> std::list<StringWrapper>.
I think this is the correct C++20 behaviour.
The library checks whether lhs <=> rhs is valid, and if so, it uses that.
Otherwise, it synthesizes a three-way comparison using operator<.
Because your type is implicitly convertible to something that is three-way
comparable, the lhs <=> rhs expression is valid, and so that's what gets used.
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Bug c++/109738] C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator
2023-05-04 15:48 [Bug c++/109738] New: C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator szhong at perforce dot com
2023-05-04 18:15 ` [Bug c++/109738] " pinskia at gcc dot gnu.org
2023-05-10 20:52 ` redi at gcc dot gnu.org
@ 2023-05-11 19:32 ` szhong at perforce dot com
2 siblings, 0 replies; 4+ messages in thread
From: szhong at perforce dot com @ 2023-05-11 19:32 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109738
--- Comment #3 from Scott Zhong <szhong at perforce dot com> ---
Is it very problematic if this is the correct behavior C++20 behaviour. For
example,
#include <compare>
#include <iostream>
struct IntWrapper {
int value;
constexpr IntWrapper(int value): value{value} { }
auto operator<=>(const IntWrapper&) const = default;
bool operator==(const IntWrapper&) const = default;
};
struct Derived : public IntWrapper
{
int value2;
Derived() :
IntWrapper(0),
value2(0) { }
bool operator<(const Derived&) const {
std::cout << "Derived::operator<()" << std::endl;
return false;
}
};
int main()
{
Derived a,b;
std::cout << (a <=> b < 0) << std::endl;
return 0;
}
Derived::operator<() is not called, only IntWrapper::operator<=>() is called.
The scenario is IntWrapper has been updated to utilize spaceship operator but
the Derived class (downstream customers) hasn't been able to update their code
to provide the spaceship operator yet. It could potentially be hard to debug
that this scenario is happening.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-05-11 19:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-04 15:48 [Bug c++/109738] New: C++20 implicit conversion is used during spaceship operator resolution instead of class's operator< for classes without spaceship operator szhong at perforce dot com
2023-05-04 18:15 ` [Bug c++/109738] " pinskia at gcc dot gnu.org
2023-05-10 20:52 ` redi at gcc dot gnu.org
2023-05-11 19:32 ` szhong at perforce dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).