Skip to content

<optional>: Potential constraint recursion for operator<=>(const optional<T>&, const U&) #1674

@CaseyCarter

Description

@CaseyCarter

While implementing <=> support for std::optional we stumbled across what appears to be constraint recursion for the operator<=> signature specified in [optional.comp.with.t]/25 when the second argument is a specialization of optional. Specifically, checking three_way_comparable_with seems to recurse via checking the constraint that e.g. < is viable for operator<(const optional<T>&, const optional<U>&), which it certainly is if <=> is provided by the first signature. We avoided the recursion by adding an additional constraint to the first signature requiring that U is not a specialization of optional, which is checked before the three_way_comparable_with constraint.

STL/stl/inc/optional

Lines 646 to 650 in 4c862ee

template <class _Ty1, class _Ty2>
requires (!_Is_specialization_v<_Ty2, optional>) // TRANSITION, GH-1674
&& three_way_comparable_with<_Ty1, _Ty2>
_NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2>
operator<=>(const optional<_Ty1>& _Left, const _Ty2& _Right) {

Looking at it now (with the workaround disabled) the recursion only manifests when compiling with Clang. Given how differently Clang and MSVC handle C++20 relational operator rewrites it's not clear to me if the constraint recursion is real or an artifact of said rewrites in Clang. We need to reduce this to something library-free and then determine whether the bug is in Clang or the C++ Standard and deal with it appropriately. (I will nonetheless tag this "LWG issue needed" for the time being.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    LWG issue neededA wording defect that should be submitted to LWG as a new issuefixedSomething works now, yay!spaceshipC++20 operator <=>

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions