This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.

3754. Class template expected synopsis contains declarations that do not match the detailed description

Section: 22.8.6.1 [expected.object.general] Status: C++23 Submitter: S. B. Tam Opened: 2022-08-23 Last modified: 2024-01-29

Priority: Not Prioritized

View all other issues in [expected.object.general].

View all issues with C++23 status.

Discussion:

22.8.6.1 [expected.object.general] declares the following constructors:

template<class G>
  constexpr expected(const unexpected<G>&);
template<class G>
  constexpr expected(unexpected<G>&&);

But in [expected.object.ctor], these constructors are declared as:

template<class G>
  constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
template<class G>
  constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);

Note that they have no explicit-specifiers in 22.8.6.1 [expected.object.general], but are conditionally explicit in [expected.object.ctor].

I presume that 22.8.6.1 [expected.object.general] is missing a few explicit(see below).

The same inconsistency exists in 22.8.7 [expected.void].

[2022-09-05; Jonathan Wakely provides wording]

In N4910 the expected synopses had explicit(see below) on the copy and move constructors. That was fixed editorially, but this other inconsistency was not noticed.

[2022-09-07; Moved to "Ready" at LWG telecon]

[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4917.

  1. Change 22.8.6.1 [expected.object.general] as indicated:

    // 22.8.6.2, constructors
    constexpr expected();
    constexpr expected(const expected&);
    constexpr expected(expected&&) noexcept(see below);
    template<class U, class G>
      constexpr explicit(see below) expected(const expected<U, G>&);
    template<class U, class G>
      constexpr explicit(see below) expected(expected<U, G>&&);
    
    template<class U = T>
      constexpr explicit(see below) expected(U&& v);
    
    template<class G>
      constexpr explicit(see below) expected(const unexpected<G>&);
    template<class G>
      constexpr explicit(see below) expected(unexpected<G>&&);
    
    template<class... Args>
      constexpr explicit expected(in_place_t, Args&&...);
    
  2. Change 22.8.7.1 [expected.void.general] as indicated:

    // 22.8.7.2, constructors
    constexpr expected() noexcept;
    constexpr expected(const expected&);
    constexpr expected(expected&&) noexcept(see below);
    template<class U, class G>
      constexpr explicit(see below) expected(const expected<U, G>&&);
    
    template<class G>
      constexpr explicit(see below) expected(const unexpected<G>&);
    template<class G>
      constexpr explicit(see below) expected(unexpected<G>&&);
    
    constexpr explicit expected(in_place_t) noexcept;