22 General utilities library [utilities]
22.8.7 Partial specialization of expected for void types [expected.void]
template<class T, class E> requires is_void_v<T>
class expected<T, E> {
public:
  using value_type = T;
  using error_type = E;
  using unexpected_type = unexpected<E>;
  template<class U>
  using rebind = expected<U, error_type>;
  
  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 U, class G>
    constexpr explicit(see below) expected(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;
  template<class... Args>
    constexpr explicit expected(unexpect_t, Args&&...);
  template<class U, class... Args>
    constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...);
  
  constexpr ~expected();
  
  constexpr expected& operator=(const expected&);
  constexpr expected& operator=(expected&&) noexcept(see below);
  template<class G>
    constexpr expected& operator=(const unexpected<G>&);
  template<class G>
    constexpr expected& operator=(unexpected<G>&&);
  constexpr void emplace() noexcept;
  
  constexpr void swap(expected&) noexcept(see below);
  friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
  
  constexpr explicit operator bool() const noexcept;
  constexpr bool has_value() const noexcept;
  constexpr void operator*() const noexcept;
  constexpr void value() const &;                                           
  constexpr void value() &&;                                                
  constexpr const E& error() const & noexcept;
  constexpr E& error() & noexcept;
  constexpr const E&& error() const && noexcept;
  constexpr E&& error() && noexcept;
  template<class G = E> constexpr E error_or(G&&) const &;
  template<class G = E> constexpr E error_or(G&&) &&;
  
  template<class F> constexpr auto and_then(F&& f) &;
  template<class F> constexpr auto and_then(F&& f) &&;
  template<class F> constexpr auto and_then(F&& f) const &;
  template<class F> constexpr auto and_then(F&& f) const &&;
  template<class F> constexpr auto or_else(F&& f) &;
  template<class F> constexpr auto or_else(F&& f) &&;
  template<class F> constexpr auto or_else(F&& f) const &;
  template<class F> constexpr auto or_else(F&& f) const &&;
  template<class F> constexpr auto transform(F&& f) &;
  template<class F> constexpr auto transform(F&& f) &&;
  template<class F> constexpr auto transform(F&& f) const &;
  template<class F> constexpr auto transform(F&& f) const &&;
  template<class F> constexpr auto transform_error(F&& f) &;
  template<class F> constexpr auto transform_error(F&& f) &&;
  template<class F> constexpr auto transform_error(F&& f) const &;
  template<class F> constexpr auto transform_error(F&& f) const &&;
  
  template<class T2, class E2> requires is_void_v<T2>
    friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
  template<class E2>
    friend constexpr bool operator==(const expected&, const unexpected<E2>&);
private:
  bool has_val;         
  union {
    E unex;             
  };
};
Any object of type 
expected<T, E> either
represents a value of type 
T, or
contains a value of type 
E within its own storage
.Implementations are not permitted to use additional storage,
such as dynamic memory, to allocate the object of type 
E.Member 
has_val indicates whether the 
expected<T, E> object
represents a value of type 
T.A program that instantiates
the definition of the template 
expected<T, E> with
a type for the 
E parameter that
is not a valid template argument for 
unexpected is ill-formed
.E shall meet the requirements of
Cpp17Destructible (Table 
35)
.