This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
std::indirect
's operator==
still does not support incomplete typesSection: 20.4.1.8 [indirect.relops], 20.4.1.9 [indirect.comp.with.t] Status: New Submitter: Hewill Kang Opened: 2025-08-24 Last modified: 2025-08-24
Priority: Not Prioritized
View all issues with New status.
Discussion:
std::indirect
's `operator==
intentionally
uses Mandates instead of Constraints to support incomplete types. However, its
function signature has the following noexcept
specification:
template<class U, class AA> constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs) noexcept(noexcept(*lhs == *rhs));
That is, we check whether the expression *lhs == *rhs
throws, which unfortunately leads to
the following hard error:
struct Incomplete;
static_assert(std::equality_comparable<std::indirect<Incomplete>>);
// hard error, no match for 'operator==' (operand types are 'const Incomplete' and 'const Incomplete')
This makes operator==
not SFINAE-friendly for incomplete types, which defeats the purpose.
noexcept(*lhs == *rhs)
seems insufficient because the result of *lhs == *rhs
might still throw during conversion to bool
.
Proposed resolution:
This wording is relative to N5014.
[Drafting note:: We introduce the exposition-only function
Please note that the seemingly unresolvedFUN
below to mimic the implicit conversion tobool
. As a drive-by effect this helps us simplifying (and clarifying, see LWG 484(i)) the existing Mandates element.T
in therequires
expression below names the first template parameter of theindirect
class template. ]
Modify 20.4.1.8 [indirect.relops] as indicated:
template<class U, class AA> constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs) noexcept(noexcept(*lhs == *rhs)see below);-?- Let
FUN
denote the exposition-only functionbool FUN(bool) noexcept;-1- Mandates: The expression
-2- Returns: IfFUN(*lhs == *rhs)
is well-formedand its result is convertible to.bool
lhs
is valueless orrhs
is valueless,lhs.valueless_after_move() == rhs.valueless_after_move()
; otherwise*lhs == *rhs
. -?- Remarks: The exception specification is equivalent to:requires (const T& lhs, const U& rhs) { { FUN(lhs == rhs) } noexcept; }
Modify 20.4.1.9 [indirect.comp.with.t] as indicated:
template<class U> constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(noexcept(*lhs == rhs)see below);-?- Let
FUN
denote the exposition-only functionbool FUN(bool) noexcept;-1- Mandates: The expression
-2- Returns: IfFUN(*lhs == rhs)
is well-formedand its result is convertible to.bool
lhs
is valueless,false
; otherwise*lhs == rhs
. -?- Remarks: The exception specification is equivalent to:requires (const T& lhs, const U& rhs) { { FUN(lhs == rhs) } noexcept; }