[/
 / Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 /
 / Distributed under the Boost Software License, Version 1.0. (See accompanying
 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 /]

[section:Sender Sender concepts]

[heading sender and sender_to]

    template<class S>
      concept sender =
        move_constructible<remove_cvref_t<S>> &&
        !requires {
          typename sender_traits<remove_cvref_t<S>>::__unspecialized; // exposition only
        };

    template<class S, class R>
      concept sender_to =
        sender<S> &&
        receiver<R> &&
        requires (S&& s, R&& r) {
          execution::connect((S&&) s, (R&&) r);
        };

None of these operations shall introduce data races as a result of concurrent
invocations of those functions from different threads.

A sender type's destructor shall not block pending completion of the submitted
function objects. 

[inline_note The ability to wait for completion of submitted function objects
may be provided by the associated execution context.]

[heading typed_sender]

A sender is [*typed] if it declares what types it sends through a receiver's
channels. The `typed_sender` concept is defined as:

    template<template<template<class...> class Tuple, template<class...> class Variant> class>
      struct has-value-types; // exposition only

    template<template<class...> class Variant>
      struct has-error-types; // exposition only

    template<class S>
      concept has-sender-types = // exposition only
        requires {
          typename has-value-types<S::template value_types>;
          typename has-error-types<S::template error_types>;
          typename bool_constant<S::sends_done>;
        };

    template<class S>
      concept typed_sender =
        sender<S> &&
        has-sender-types<sender_traits<remove_cvref_t<S>>>;

[endsect]
