'Missing MFC CString operator==() overloads when using C++20 in VS2022 (17.0.6)

Update: This was fixed in VS2022 v17.2 Preview 1

When I set my MFC project to use C++20, I'm getting errors when comparing string literals with CString instances.

For example:

CString s1 = _T("s1");
    
// this works
if (s1 == _T("s1")) {
  cout << "Match!"
}

// this generates a compiler error 
if (_T("s1") == s1) {
  cout << "Match!";
}

According to the CStringT documentation, there are a bunch of == overloads:

friend bool operator==(const CStringT& str1, const CStringT& str2) throw();
friend bool operator==(const CStringT& str1, PCXSTR psz2) throw();
friend bool operator==(const CStringT& str1, PCYSTR psz2) throw();
friend bool operator==(const CStringT& str1, XCHAR ch2) throw();
-> friend bool operator==(PCXSTR psz1, const CStringT& str2) throw();
friend bool operator==(PCYSTR psz1, const CStringT& str2,) throw();
friend bool operator==(XCHAR ch1, const CStringT& str2,) throw();

I marked the one I think it should be finding. However, it doesn't seem to even consider that overload:

error C2666: '==': 3 overloads have similar conversions
message : could be 'bool operator ==(const D2D1_RECT_U &,const D2D1_RECT_U &)'
message : or       'bool operator ==(const D2D1_SIZE_U &,const D2D1_SIZE_U &)'
message : or       'bool operator ==(const DEVPROPCOMPKEY &,const DEVPROPCOMPKEY &)'
message : or       'bool operator ==(const DEVPROPKEY &,const DEVPROPKEY &)'
message : or       'int operator ==(const PROPERTYKEY &,const PROPERTYKEY &)'
message : or       'bool operator ==(const GUID &,const GUID &)'
message : or       'bool ATL::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &) noexcept' [found using argument-dependent lookup]
message : or       'bool ATL::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,const wchar_t *) noexcept' [found using argument-dependent lookup]
message : or       'bool ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,const char *)' [found using argument-dependent lookup]
message : or       'bool ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,wchar_t) noexcept' [found using argument-dependent lookup]
message : or 'bool operator ==(const GUID &,const GUID &)' [synthesized expression 'y == x']
message : or 'bool ATL::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &) noexcept' [synthesized expression 'y == x']
message : or 'bool ATL::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,const wchar_t *) noexcept' [synthesized expression 'y == x']
message : or 'bool ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,const char *)' [synthesized expression 'y == x']
message : or 'bool ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator ==(const ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>> &,wchar_t) noexcept' [synthesized expression 'y == x']
message : or 'int operator ==(const PROPERTYKEY &,const PROPERTYKEY &)' [synthesized expression 'y == x']
message : or 'bool operator ==(const DEVPROPKEY &,const DEVPROPKEY &)' [synthesized expression 'y == x']
message : or 'bool operator ==(const DEVPROPCOMPKEY &,const DEVPROPCOMPKEY &)' [synthesized expression 'y == x']
message : or 'bool operator ==(const D2D1_SIZE_U &,const D2D1_SIZE_U &)' [synthesized expression 'y == x']
message : or 'bool operator ==(const D2D1_RECT_U &,const D2D1_RECT_U &)' [synthesized expression 'y == x']
message : or       'built-in C++ operator==(const wchar_t [3], const wchar_t [3])'
message : or       'built-in C++ operator==(const wchar_t *, const wchar_t *)'
message : while trying to match the argument list '(const wchar_t [3], CString)'

So I went to the header file (cstringt.h) and found that a bunch of the friend functions, including the one I marked, are #ifdef'd out because __cpp_lib_three_way_comparison is #define'd.

Does the spaceship operator somehow make a bunch of those friend functions unnecessary? If so, what's the fix? I know I can change my comparison to s1 == _T("s1") but I like having a constant expression on the left in case I accidentally use = rather than ==.



Solution 1:[1]

This was fixed by Microsoft in 17.2 Preview 1 according to https://developercommunity.visualstudio.com/t/Missing-comparison-operators-between-LPC/1614285.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 criddell