Doc. no: P0112R0 Date: 2015-09-25 Revises: N4478 Reply-To: Christopher Kohlhoff <chris@kohlhoff.com>
In the June 2014 committee meeting in Rapperswil, LEWG requested that Boost.Asio-based N2175 Networking Library Proposal for TR2 (Revision 1) be updated for C++14 and brought forward as a proposed Networking Technical Specification. This document is that revision. As well as updating the proposal for C++14, it incorporates improvements to Asio that are based on the widespread field experience accumulated since 2007.
The Boost.Asio library, from which this proposal is derived, has been deployed in numerous systems, from large (including internet-facing HTTP servers, instant messaging gateways and financial markets applications) to small (mobile phones and embedded systems). The Asio library supports, or has been ported to, many operating systems including Linux, Mac OS X, Windows (native), Windows Runtime, Solaris, FreeBSD, NetBSD, OpenBSD, HP-UX, Tru64, AIX, iOS, Android, WinCE, Symbian, vxWorks and QNX Neutrino.
This revision includes changes to address the remaining issues from the LWG wording review held in Cologne in February 2015, as well applying design changes following LEWG review in Lenexa. As the changes are too extensive to list here, readers may wish to view the GitHub page for this proposal at https://github.com/chriskohlhoff/asio-tr2/ for further information.
Since the previous revision, the design changes of note include:
io_service to
          io_context.
        wrap()
          to bind_executor().
        package()
          to be the function call operator of use_future.
        const_buffers_1
          and mutable_buffers_1 classes.
          The buffer sequence requirements have been updated, and const_buffer
          and mutable_buffer now
          satisfy these requirements directly.
        data()
          and size()
          member functions to const_buffer
          and mutable_buffer, replacing
          buffer_cast<>()
          and buffer_size()
          respectively.
        An almost complete implementation of the proposal text may be found in a variant of Asio that stands alone from Boost. This variant is available at https://github.com/chriskohlhoff/asio/tree/master.
Unfamiliar readers are encouraged to look to the Boost.Asio documentation and examples for a more complete picture of the use of the library.
However, to give some idea of the flavour of the proposed library, consider the following sample code. This is part of a server program that echoes the characters it receives back to the client in upper case.
template <typename Iterator> void uppercase(Iterator begin, Iterator end) { std::locale loc(""); for (Iterator iter = begin; iter != end; ++iter) *iter = std::toupper(*iter, loc); } void sync_connection(tcp::socket& socket) { try { std::vector<char> buffer_space(1024); for (;;) { std::size_t length = socket.read_some(buffer(buffer_space)); uppercase(buffer_space.begin(), buffer_space.begin() + length); write(socket, buffer(buffer_space, length)); } } catch (std::system_error& e) { // ... } }
The synchronous operations used above are functions that do not return control to the caller until the corresponding operating system operation completes. In Asio-based programs their use cases typically fall into two categories:
Next, the equivalent code developed using asynchronous operations might look something like this:
class async_connection : public std::enable_shared_from_this<async_connection> { public: async_connection(tcp::socket socket) : socket_(std::move(socket)) { } void start() { do_read(); } private: void do_read() { auto self(shared_from_this()); socket_.async_read_some(buffer(buffer_space_), [this, self](std::error_code ec, std::size_t length) { if (!ec) { uppercase(buffer_space_.begin(), buffer_space_.begin() + length); do_write(length); } }); } void do_write(std::size_t length) { auto self(shared_from_this()); async_write(socket_, buffer(buffer_space_, length), [this, self](std::error_code ec, std::size_t /*length*/) { if (!ec) { do_read(); } }); } tcp::socket socket_; std::vector<char> buffer_space_{1024}; };
Asynchronous operations do not block the caller, but instead involve the delivery of a notification to the program when the corresponding operating system operation completes. Most non-trivial Asio-based programs will make use of asynchronous operations.
While the code may appear more complex due to the inverted flow of control, it allows a knowledgeable programmer to write code that will scale to a great many concurrent connections. However, this proposal uses the asynchronous model described in [N4045]. This is an extensible model that allows the asynchronous operations to support a variety of composition and notification mechanisms, and these mechanisms may alleviate this complexity. This includes futures:
std::future<std::size_t> fut = socket.async_read_some(buffer(buffer_space), use_future); // ... std::size_t length = fut.get();
and, through library extensions, coroutines:
void coro_connection(tcp::socket& socket, yield_context yield) { try { std::vector<char> buffer_space(1024); for (;;) { std::size_t length = socket.async_read_some(buffer(buffer_space), yield); uppercase(buffer_space.begin(), buffer_space.begin() + length); async_write(socket, buffer(buffer_space, length), yield); } } catch (std::system_error& e) { // ... } }
Finally, for many applications, networking is not a core feature, nor is it seen as a core competency of the application’s programmers. To cater to these use cases, the proposal provides a high-level interface to TCP sockets that is designed around the familiar C++ I/O streams framework.
Using the library in this way is as easy as opening a stream object with the remote host’s details:
tcp::iostream s("www.boost.org", "http");
Once connected, you send and receive any data as needed. In this case you send a request:
s << "GET / HTTP/1.0\r\n"; s << "Host: www.boost.org\r\n"; s << "Accept: */*\r\n"; s << "Connection: close\r\n\r\n";
Then receive and process the response:
std::string header; while (std::getline(s, header) && header != "\r") std::cout << header << "\n"; std::cout << s.rdbuf();
You can set a timeout to detect unresponsive connections:
s.expires_after(std::chrono::seconds(60));
      And, if at any time there is an error, the tcp::iostream
      class’s error()
      member function may be used to obtain an error_code
      that identifies the reason for failure:
    
if (!s) { std::cout << "Unable to connect: " << s.error().message() << "\n"; return 1; }
Problem areas addressed by this proposal include:
Features that are considered outside the scope of this proposal include:
The bulk of the library interface is intended for use by developers with at least some understanding of networking concepts (or a willingness to learn). A high level iostreams interface supports simple use cases and permits novices to develop network code without needing to get into too much depth.
The interface is based on the BSD sockets API, which is widely implemented and supported by extensive literature. It is also used as the basis of networking APIs in other languages (e.g. Java). Unsafe practices of the BSD sockets API, e.g. lack of compile-time type safety, are not included.
Asynchronous support is derived from the Proactor design pattern as implemented by the ADAPTIVE Communication Environment [ACE], and is influenced by the design of the Symbian C++ sockets API [SYMBIAN], which supports synchronous and asynchronous operations side-by-side. The Microsoft .NET socket classes [MS-NET] and the Extended Sockets API [ES-API] developed by The Open Group support similar styles of network programming.
This is a pure library proposal. It does not add any new language features, nor does it alter any existing standard library headers. It makes additions to experimental headers that may also be modified by other Technical Specifications.
This library can be implemented using compilers that conform to the C++14 standard. An implementation of this library requires operating system-specific functions that lie outside the C++14 standard.
The asynchronous operations defined in this proposal use the asynchronous model previously described in [N4045]. With the extensible asynchronous model presented in that paper, the user has the ability to select an asynchronous approach that is appropriate to each use case. With these library foundations, a single extensible asynchronous model can support a variety of composition methods, including:
To facilitate the coordination of asynchronous operations in multithreaded programs, the asynchronous model also utilises the executors design described and specified in [P0113].
As executors and the extensible asynchronous model are a prerequisite for the networking library, the proposed text below incorporates a complete specification of these facilities.
<experimental/executor> synopsisasync_resultasync_completionassociated_allocatorget_associated_allocatorexecution_contextexecution_context::serviceis_executoruses_executorassociated_executorget_associated_executorexecutor_binderexecutor_binder constructorsexecutor_binder accessexecutor_binder invocationasync_resultassociated_allocatorassociated_executorbind_executorexecutor_work_guardmake_work_guardsystem_executorsystem_contextbad_executorexecutordispatchpostdeferstranduse_future_tasync_result
        for packaged_task<experimental/buffer> synopsismutable_bufferconst_bufferbuffer_sizebuffer_copydynamic_vector_bufferdynamic_string_buffertransfer_alltransfer_at_leasttransfer_exactly<experimental/socket> synopsissocket_basebasic_socketbasic_datagram_socketbasic_stream_socketbasic_socket_acceptor<experimental/internet> synopsisip::addressip::address_v4ip::address_v6ip::bad_address_castip::basic_address_iterator specializationsip::basic_address_range specializationsip::network_v4ip::network_v6ip::basic_endpointip::basic_resolver_entryip::basic_resolver_resultsip::resolver_baseip::basic_resolverip::tcpip::udpThis Technical Specification describes extensions to the C++ Standard Library. This Technical Specification specifies requirements for implementations of an interface that computer programs written in the C++ programming language may use to perform operations related to networking, such as operations involving sockets, timers, buffer management, host name resolution and internet protocols. This Technical Specification is applicable to information technology systems that can perform network operations, such as those with operating systems that conform to the POSIX interface. This Technical Specification is applicable only to vendors who wish to provide the interface it describes.
Conformance is specified in terms of behavior. Ideal behavior is not always implementable, so the conformance sub-clauses take that into account.
Some behavior is specified by reference to POSIX. How such behavior is actually implemented is unspecified.
[Note: This constitutes an "as if" rule allowing implementations to call native operating system or other APIs. —end note]
Implementations are encouraged to provide such behavior as it is defined by POSIX. Implementations shall document any behavior that differs from the behavior defined by POSIX. Implementations that do not support exact POSIX behavior are encouraged to provide behavior as close to POSIX behavior as is reasonable given the limitations of actual operating systems and file systems. If an implementation cannot provide any reasonable behavior, the implementation shall report an error as specified in Error Reporting.
[Note: This allows users to rely on an exception being thrown or an error code being set when an implementation cannot provide any reasonable behavior. —end note]
Implementations are not required to provide behavior that is not supported by a particular operating system.
          This Technical Specification defines conditially-supported features, in
          the form of additional member functions on types that satisfy Protocol, Endpoint, SettableSocketOption, GettableSocketOption or IoControlCommand
          requirements.
        
[Note: This is so that, when the additional member functions are available, C++ programs may extend the library to add support for other protocols and socket options. —end note]
For the purposes of this Technical Specification, implementations that provide all of the additional member functions are known as extensible implementations.
[Note: Implementations are encouraged to provide the additional member functions, where possible. It is intended that POSIX and Windows implementations will provide them. —end note]
The following referenced documents are indispensable for the application of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
        [Note: The programming language and library described
        in ISO/IEC 14882 is herein called the C++ Standard. References to clauses
        within the C++ Standard are written as "C++Std [xref]". 
        The operating system interface described in ISO/IEC 9945 is herein called
        POSIX. —end note]
      
This Technical Specification mentions commercially available operating systems for purposes of exposition. [1]
Unless otherwise specified, the whole of the C++ Standard's Library introduction (C++Std [library]) is included into this Technical Specification by reference.
        The components described in this Technical Specification are experimental
        and not part of the C++ standard library. All components described in this
        Technical Specification are declared in namespace std::experimental::net::v1 or a sub-namespace thereof unless otherwise
        specified. The headers described in this technical specification shall import
        the contents of std::experimental::net::v1
        into std::experimental::net as if by:
      
namespace std { namespace experimental { namespace net { inline namespace v1 {} } } }
        Unless otherwise specified, references to other entities described in this
        Technical Specification are assumed to be qualified with std::experimental::net::v1::, references
        to entities described in the C++ standard are assumed to be qualified with
        std::,
        and references to entities described in C++ Extensions for Library Fundamentals
        are assumed to be qualified with std::experimental::fundamentals_v1::.
      
[defs.host.byte.order] See section 3.194 of POSIX Base Definitions, Host Byte Order.
[defs.net.byte.order] See section 3.238 of POSIX Base Definitions, Network Byte Order.
[defs.sync.op] A synchronous operation is one where control is not returned until the operation completes.
[defs.async.op] An asynchronous operation is one where control is returned immediately without waiting for the operation to complete. Multiple asynchronous operations may be executed concurrently.
[defs.orderly.shutdown] The procedure for shutting down a stream after all work in progress has been completed, without loss of data.
This section describes tentative plans for future versions of this technical specification and plans for moving content into future versions of the C++ Standard.
        The C++ committee may release new versions of this technical specification,
        containing networking library extensions we hope to add to a near-future
        version of the C++ Standard. Future versions will define their contents in
        std::experimental::net::v2,
        std::experimental::net::v3,
        etc., with the most recent implemented version inlined into std::experimental::net.
      
        When an extension defined in this or a future version of this technical specification
        represents enough existing practice, it will be moved into the next version
        of the C++ Standard by replacing the experimental::net::vN segment of its namespace with net, and by removing the experimental/
        prefix from its header's path.
      
These macros allow users to determine which version of this Technical Specification is supported by the headers defined by the specification. All headers in this Technical Specification shall supply the following macro definition:
#define __cpp_lib_experimental_net yyyymm
If an implementation supplies all of the conditionally-supported features specified in [conformance.conditional], all headers in this Technical Specification shall supply the following macro definition:
#define __cpp_lib_experimental_net_extensible yyyymm
        [Note: The value of the macros __cpp_lib_experimental_net
        and __cpp_lib_experimental_net_extensible
        is yyyymm where yyyy is the year and mm
        the month when the version of the Technical Specification was completed.
        —end note]
      
This subclause describes the conventions used to specify this Technical Specification, in addition to those conventions specified in C++Std [description].
In addition to the elements defined in C++Std [structure.specifications], descriptions of function semantics contain the following elements (as appropriate):
— Completion signature: - if the function initiates an asynchronous operation, specifies the signature of a completion handler used to receive the result of the operation.
            Several classes defined in this Technical Specification are nested classes.
            For a specified nested class A::B,
            an implementation is permitted to define A::B
            as a synonym for a class with equivalent functionality to class A::B.
            [Note: When A::B
            is a synonym for another type A
            shall provide a nested type B,
            to emulate the injected class name. —end note]
          
          Most synchronous network library functions provide two overloads, one that
          throws an exception to report system errors, and another that sets an
          error_code (C++Std [syserr]).
        
          [Note: This supports two common use cases:
          
 — Uses where system errors are truly exceptional and indicate a serious
          failure. Throwing an exception is the most appropriate response.
          
 — Uses where system errors are routine and do not necessarily represent
          failure. Returning an error code is the most appropriate response. This
          allows application specific error handling, including simply ignoring the
          error.
 
 —end note]
        
          Functions not having an argument of type
          error_code&
          report errors as follows, unless otherwise specified:
        
          — When a call by the implementation to an operating system or other underlying
          API results in an error that prevents the function from meeting its specifications,
          the function exits via an exception of a type that would match a handler
          of type system_error.
        
— Destructors throw nothing.
          Functions having an argument of type error_code& report errors as follows, unless otherwise
          specified:
        
          — If a call by the implementation to an operating system or other underlying
          API results in an error that prevents the function from meeting its specifications,
          the error_code&
          argument ec is set as appropriate
          for the specific error. Otherwise, the ec
          argument is set such that !ec is true.
        
          Where a function is specified as two overloads, with and without an argument
          of type error_code&:
        
R f(A1 a1, A2 a2, ..., AN aN); R f(A1 a1, A2 a2, ..., AN aN, error_code& ec);
          then, when R is non-void, the effects of the first overload
          are as if:
        
error_code ec; R r(f(a1, a2, ..., aN, ec)); if (ec) throw system_error(ec, __func__); return r;
          otherwise, when R
          is void, the effects of the
          first overload are as if:
        
error_code ec; f(a1, a2, ..., aN, ec); if (ec) throw system_error(ec, __func__);
except that the type thrown may differ as specified above.
For both overloads, failure to allocate storage is reported by throwing an exception as described in the C++ standard (C++Std [res.on.exception.handling]).
          In this Technical Specification, when a type requirement is specified using
          two function call expressions f,
          with and without an argument ec
          of type error_code:
        
f(a1, a2, ..., aN) f(a1, a2, ..., aN, ec)
then the effects of the first call expression of f shall be as described for the first overload above.
          Asynchronous network library functions in this Technical Specification
          are identified by having the prefix async_
          and take a completion handler [async.reqmts.async.token].
          These asynchronous operations report errors as follows:
        
          — If a call by the implementation to an operating system or other underlying
          API results in an error that prevents the asynchronous operation from meeting
          its specifications, the completion handler is invoked with an error_code value ec
          that is set as appropriate for the specific error. Otherwise, the error_code value ec
          is set such that !ec
          is true.
        
          — Asynchronous operations shall not fail with an error condition that indicates
          interruption of an operating system or underlying API by a signal [Note:
          Such as POSIX error number EINTR
          —end note] . Asynchronous operations shall not fail
          with any error condition associated with non-blocking operations [Note:
          Such as POSIX error numbers EWOULDBLOCK,
          EAGAIN, or EINPROGRESS; Windows error numbers WSAEWOULDBLOCK or WSAEINPROGRESS
          —end note] .
        
          In this Technical Specification, when a type requirement is specified as
          a call to a function or member function having the prefix async_, then the function shall satisfy
          the error reporting requirements described above.
        
          Unless otherwise specified, when the behavior of a synchronous or asynchronous
          operation is defined "as if" implemented by a POSIX function,
          the error_code produced
          by the function shall meet the following requirements:
        
          — If the failure condition is one that is listed by POSIX for that function,
          the error_code shall compare
          equal to the error's corresponding enum
          class errc
          (C++Std [syserr]) or enum class resolver_errc constant.
        
          — Otherwise, the error_code
          shall be set to an implementation-defined value that reflects the underlying
          operating system error.
        
          [Example: The POSIX specification for shutdown
          lists EBADF as one of its
          possible errors. If a function that is specified "as if" implemented
          by shutdown
          fails with EBADF then the
          following condition holds for the error_code
          value ec: ec == errc::bad_file_descriptor —end example]
        
          When the description of a function contains the element Error
          conditions, this lists conditions where the operation may fail.
          The conditions are listed, together with a suitable explanation, as enum class
          constants. Unless otherwise specified, this list is a subset of the failure
          conditions associated with the function.
        
          Some POSIX functions referred to in this Technical Specification may report
          errors by raising a SIGPIPE
          signal. Where a synchronous or asynchronous operation is specified in terms
          of these POSIX functions, the generation of SIGPIPE
          is suppressed and an error condition corresponding to POSIX EPIPE is produced instead.
        
Table 1. Networking library summary
| Clause | Header(s) | 
|---|---|
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | 
Throughout this Technical Specification, the names of the template parameters are used to express type requirements, as listed in the table below.
Table 2. Template parameters and type requirements
| template parameter name | type requirements | 
|---|---|
| 
                   | |
| 
                   | C++Std [allocator.requirements] | 
| 
                   | |
| 
                   | |
| 
                   | C++Std [time.clock.req] | 
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | |
| 
                   | 
#include <experimental/executor> #include <experimental/io_context> #include <experimental/timer> #include <experimental/buffer> #include <experimental/socket> #include <experimental/internet>
          [Note: This header is provided as a convenience for
          programs so that they may access all networking facilities via a single,
          self-contained #include.
          —end note]
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class execution_context; template<class T, class Executor> class executor_binder; template<class Executor> class executor_work_guard; class system_executor; class executor; template<class Executor> class strand; class io_context; template<class Clock> struct wait_traits; template<class Clock, class WaitTraits = wait_traits<Clock>> class basic_waitable_timer; typedef basic_waitable_timer<chrono::system_clock> system_timer; typedef basic_waitable_timer<chrono::steady_clock> steady_timer; typedef basic_waitable_timer<chrono::high_resolution_clock> high_resolution_timer; template<class Protocol> class basic_socket; template<class Protocol> class basic_datagram_socket; template<class Protocol> class basic_stream_socket; template<class Protocol> class basic_socket_acceptor; template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_streambuf; template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_iostream; namespace ip { class address; class address_v4; class address_v6; class address_iterator_v4; class address_iterator_v6; class address_range_v4; class address_range_v6; class network_v4; class network_v6; template<class InternetProtocol> class basic_endpoint; template<class InternetProtocol> class basic_resolver_entry; template<class InternetProtocol> class basic_resolver_results; template<class InternetProtocol> class basic_resolver; class tcp; class udp; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Default template arguments are described as appearing both in <netfwd> and in the synopsis of other headers
          but it is well-formed to include both <netfwd>
          and one or more of the other headers. [Note: It is
          the implementation’s responsibility to implement headers so that including
          <netfwd> and other headers does not violate
          the rules about multiple occurrences of default arguments. —end
          note]
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class CompletionToken, class Signature, class = void> class async_result; template<class CompletionToken, class Signature> struct async_completion; template<class T, class ProtoAllocator = allocator<void>> struct associated_allocator; template<class T, class ProtoAllocator = allocator<void>> using associated_allocator_t = typename associated_allocator<T, ProtoAllocator>::type; // get_associated_allocator: template<class T> associated_allocator_t<T> get_associated_allocator(const T& t) noexcept; template<class T, class ProtoAllocator> associated_allocator_t<T, ProtoAllocator> get_associated_allocator(const T& t, const ProtoAllocator& a) noexcept; enum class fork_event { prepare, parent, child }; class execution_context; class service_already_exists; template<class Service> Service& use_service(execution_context& ctx); template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args); template<class Service> bool has_service(execution_context& ctx) noexcept; template<class T> struct is_executor; struct executor_arg_t { }; constexpr executor_arg_t executor_arg = executor_arg_t(); template<class T, class Executor> struct uses_executor; template<class T, class Executor = system_executor> struct associated_executor; template<class T, class Executor = system_executor> using associated_executor_t = typename associated_executor<T, Executor>::type; // get_associated_executor: template<class T> associated_executor_t<T> get_associated_executor(const T& t) noexcept; template<class T, class Executor> associated_executor_t<T, Executor> get_associated_executor(const T& t, const Executor& ex) noexcept; template<class T, class ExecutionContext> associated_executor_t<T, typename ExecutionContext::executor_type> get_associated_executor(const T& t, ExecutionContext& ctx) noexcept; template<class T, class Executor> class executor_binder; template<class T, class Executor, class Signature> class async_result<executor_binder<T, Executor>, Signature>; template<class T, class Executor, class ProtoAllocator> struct associated_allocator<executor_binder<T, Executor>, ProtoAllocator>; template<class T, class Executor, class Executor1> struct associated_executor<executor_binder<T, Executor>, Executor1>; // bind_executor: template<class Executor, class T> executor_binder<decay_t<T>, Executor> bind_executor(const Executor& ex, T&& t); template<class ExecutionContext, class T> executor_binder<decay_t<T>, typename ExecutionContext::executor_type> bind_executor(ExecutionContext& ctx, T&& t); template<class Executor> class executor_work_guard; // make_work_guard: template<class Executor> executor_work_guard<Executor> make_work_guard(const Executor& ex); template<class ExecutionContext> executor_work_guard<typename ExecutionContext::executor_type> make_work_guard(ExecutionContext& ctx); template<class T> executor_work_guard<associated_executor_t<T>> make_work_guard(const T& t); template<class T, class U> auto make_work_guard(const T& t, U&& u) -> decltype(make_work_guard(get_associated_executor(t, forward<U>(u)))); class system_executor; class system_context; bool operator==(const system_executor&, const system_executor&); bool operator!=(const system_executor&, const system_executor&); class bad_executor; class executor; bool operator==(const executor& a, const executor& b) noexcept; bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept; bool operator!=(const executor& a, const executor& b) noexcept; bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept; // dispatch: template<class CompletionToken> DEDUCED dispatch(CompletionToken&& token); template<class Executor, class CompletionToken> DEDUCED dispatch(const Executor& ex, CompletionToken&& token); template<class ExecutionContext, class CompletionToken> DEDUCED dispatch(ExecutionContext& ctx, CompletionToken&& token); // post: template<class CompletionToken> DEDUCED post(CompletionToken&& token); template<class Executor, class CompletionToken> DEDUCED post(const Executor& ex, CompletionToken&& token); template<class ExecutionContext, class CompletionToken> DEDUCED post(ExecutionContext& ctx, CompletionToken&& token); // defer: template<class CompletionToken> DEDUCED defer(CompletionToken&& token); template<class Executor, class CompletionToken> DEDUCED defer(const Executor& ex, CompletionToken&& token); template<class ExecutionContext, class CompletionToken> DEDUCED defer(ExecutionContext& ctx, CompletionToken&& token); template<class Executor> class strand; template<class Executor> bool operator==(const strand<Executor>& a, const strand<Executor>& b); template<class Executor> bool operator!=(const strand<Executor>& a, const strand<Executor>& b); template<class ProtoAllocator = allocator<void>> class use_future_t; constexpr use_future_t<> use_future = use_future_t<>(); template<class ProtoAllocator, class Result, class... Args> class async_result<use_future_t<ProtoAllocator>, Result(Args...)>; template<class R, class... Args, class Signature> class async_result<packaged_task<Result(Args...)>, Signature>; } // inline namespace v1 } // namespace net } // namespace experimental template<class Allocator> struct uses_allocator<experimental::net::v1::executor, Allocator> : true_type {}; } // namespace std
[async.reqmts.proto.allocator]
            A type A meets the proto-allocator
            requirements if A is
            CopyConstructible (C++Std
            [copyconstructible]), Destructible
            (C++Std [destructible]), and allocator_traits<A>::rebind_alloc<U> meets the allocator requirements
            (C++Std [allocator.requirements]), where U
            is an object type. [Note: For example, std::allocator<void>
            meets the proto-allocator requirements but not the allocator requirements.
            —end note] No constructor, comparison operator, copy
            operation, move operation, or swap operation on these types shall exit
            via an exception.
          
            The library describes a standard set of requirements for executors.
            A type meeting the Executor
            requirements embodies a set of rules for determining how submitted function
            objects are to be executed.
          
            A type X meets the Executor requirements if it satisfies
            the requirements of CopyConstructible
            (C++Std [copyconstructible]) and Destructible
            (C++Std [destructible]), as well as the additional requirements listed
            below.
          
            No constructor, comparison operator, copy operation, move operation,
            swap operation, or member functions context,
            on_work_started, and
            on_work_finished on these
            types shall exit via an exception.
          
The executor copy constructor, comparison operators, and other member functions defined in these requirements shall not introduce data races as a result of concurrent calls to those functions from different threads.
            In the table below, x1
            and x2 denote values
            of type X, cx1 and cx2
            denote (possibly const) values of type X,
            mx1 denotes an xvalue
            of type X, f denotes a MoveConstructible
            (C++Std [moveconstructible]) function object callable with zero arguments,
            a denotes a (possibly
            const) value of type A
            meeting the Allocator
            requirements (C++Std [allocator.requirements]), and u
            denotes an identifier.
          
Table 3. Executor requirements
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      Shall not exit via an exception. | |
| 
                       | 
                      Shall not exit via an exception. | |
| 
                       | 
                       | 
                      Returns  | 
| 
                       | 
                       | 
                      Same as  | 
| 
                       | 
                       | 
                      Shall not exit via an exception. | 
| 
                       | Shall not exit via an exception. | |
| 
                       | 
                      Shall not exit via an exception. | |
| 
                       | 
                      Effects: Creates an object  | |
| 
                       | 
                      Effects: Creates an object  | 
[async.reqmts.executioncontext]
            A type X meets the ExecutionContext requirements if it
            is publicly and unambiguously derived from execution_context,
            and satisfies the additional requirements listed below.
          
            In the table below, x
            denotes a value of type X.
          
Table 4. ExecutionContext requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      type meeting  | |
| 
                       | Destroys all unexecuted function objects that were submitted via an executor object that is associated with the execution context. | |
| 
                       | 
                       | Returns an executor object that is associated with the execution context. | 
            A class is a service if it is publicly and unambiguously
            derived from execution_context::service,
            or if it is publicly and unambiguously derived from another service.
            For a service S, S::key_type shall be valid and denote
            a type (C++Std [temp.deduct]), is_base_of_v<typename
            S::key_type,
            S>
            shall be true, and S shall satisfy the Destructible
            requirements (C++Std [destructible]).
          
            The first parameter of all service constructors shall be an lvalue reference
            to execution_context.
            This parameter denotes the execution_context
            object that represents a set of services, of which the service object
            will be a member. [Note: These constructors may
            be called by the make_service
            function. —end note]
          
            A service shall provide an explicit constructor with a single parameter
            of lvalue reference to execution_context.
            [Note: This constructor may be called by the use_service function. —end
            note]
          
            [Example: 
          
class my_service : public execution_context::service { public: typedef my_service key_type; explicit my_service(execution_context& ctx); my_service(execution_context& ctx, int some_value); private: virtual void shutdown() noexcept override; ... };
—end example]
            A service's shutdown
            member function shall destroy all copies of user-defined function objects
            that are held by the service.
          
A type satisfies the signature requirements if it is a call signature (C++Std [func.def]).
An associator defines a relationship between different types and objects where, given:
            — a source object s of
            type S,
          
            — type requirements R,
            and
          
            — a candidate object c
            of type C meeting the
            type requirements R
          
            an associated type A
            meeting the type requirements R
            may be computed, and an associated object a of type A
            may be obtained.
          
            An associator shall be a class template that takes two template type
            arguments. The first template argument is the source type S. The second template argument is
            the candidate type C.
            The second template argument shall be defaulted to some default candidate
            type D that satisfies
            the type requirements R.
          
            An associator shall additionally satisfy the requirements in the table
            below. In this table, X
            is a class template that meets the associator requirements, S is the source type, s is a (possibly const) value of type
            S, C
            is the candidate type, c
            is a (possibly const) value of type C,
            D is the default candidate
            type, and d is a (possibly
            const) value of type D
            that is the default candidate object.
          
Table 5. Associator requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | |
| 
                       | The associated type. | |
| 
                       | 
                       | 
                      Returns  | 
| 
                       | 
                       | Returns the associated object. | 
            The associator's primary template shall be defined. A program may partially
            specialize the associator class template for some user-defined type
            S.
          
Finally, the associator shall provide the following type alias and function template in the enclosing namespace:
template<class S, class C = D> using X_t = typename X<S, C>::type; template<class S, class C = D> typename X<S, C>::type get_X(const S& s, const C& c = d) { return X<S, C>::get(s, c); }
            where X is replaced with the
            name of the associator class template. [Note: This
            function template is provided as a convenience, to automatically deduce
            the source and candidate types. —end note]
          
            This section uses the names Alloc1,
            Alloc2, alloc1, alloc2,
            Args, CompletionHandler,
            completion_handler,
            Executor1, Executor2, ex1,
            ex2, f,
            i, N,
            Signature, token, Ti,
            ti, work1,
            and work2 as placeholders
            for specifying the requirements below.
          
An initiating function is a function which may be called to start an asynchronous operation. A completion handler is a function object that will be invoked, at most once, with the result of the asynchronous operation.
The lifecycle of an asynchronous operation is comprised of the following events and phases:
— Event 1: The asynchronous operation is started by a call to the initiating function.
— Phase 1: The asynchronous operation is now outstanding.
— Event 2: The externally observable side effects of the asynchronous operation, if any, are fully established. The completion handler is submitted to an executor.
— Phase 2: The asynchronous operation is now completed.
— Event 3: The completion handler is called with the result of the asynchronous operation.
              In this Technical Specification, all functions with the prefix async_ are initiating functions.
            
Initiating functions:
              — are function templates with template parameter CompletionToken;
            
              — accept, as the final parameter, a completion token
              object token of type
              CompletionToken;
            
              — specify a completion signature, which is a call
              signature (C++Std [func.def]) Signature
              that determines the arguments to the completion handler.
            
              An initiating function determines the type CompletionHandler
              of its completion handler function object by performing typename async_result<decay_t<CompletionToken>, Signature>::completion_handler_type.
              The completion handler object completion_handler
              is initialized with forward<CompletionToken>(token). [Note: No other
              requirements are placed on the type CompletionToken.
              —end note]
            
              The type CompletionHandler
              must satisfy the requirements of Destructible
              (C++Std [destructible]) and MoveConstructible
              (C++Std [moveconstructible]), and be callable with the specified call
              signature.
            
              In this Technical Specification, all initiating functions specify a
              Completion signature element that defines the
              call signature Signature.
              The Completion signature elements in this Technical
              Specification have named parameters, and the results of an asynchronous
              operation are specified in terms of these names.
            
[async.reqmts.async.return.type]
              The return type of an initiating function is typename
              async_result<decay_t<CompletionToken>,
              Signature>::return_type.
            
              For the sake of exposition, this Technical Specification sometimes
              annotates functions with a return type DEDUCED. For every function
              declaration that returns DEDUCED, the meaning is equivalent to
              specifying the return type as typename
              async_result<decay_t<CompletionToken>,
              Signature>::return_type.
            
[async.reqmts.async.return.value]
An initiating function produces its return type as follows:
              — constructing an object result
              of type async_result<decay_t<CompletionToken>, Signature>, initialized as result(completion_handler); and
            
              — using result.get()
              as the operand of the return statement.
            
              [Example: Given an asynchronous operation with
              Completion signature void(R1 r1, R2 r2), an initiating function meeting these
              requirements may be implemented as follows:
            
template<class CompletionToken> auto async_xyz(T1 t1, T2 t2, CompletionToken&& token) { typename async_result<decay_t<CompletionToken>, void(R1, R2)>::completion_handler_type completion_handler(forward<CompletionToken>(token)); async_result<decay_t<CompletionToken>, void(R1, R2)> result(completion_handler); // initiate the operation and cause completion_handler to be invoked with // the result return result.get(); }
              For convenience, initiating functions may be implemented using the
              async_completion template:
            
template<class CompletionToken> auto async_xyz(T1 t1, T2 t2, CompletionToken&& token) { async_completion<CompletionToken, void(R1, R2)> init(token); // initiate the operation and cause init.completion_handler to be invoked // with the result return init.result.get(); }
—end example]
Unless otherwise specified, the lifetime of arguments to initiating functions shall be treated as follows:
— If the parameter has a pointer type or has a type of lvalue reference to non-const, the implementation may assume the validity of the pointee or referent, respectively, until the completion handler is invoked. [Note: In other words, the program must guarantee the validity of the argument until the completion handler is invoked. —end note]
— Otherwise, the implementation must not assume the validity of the argument after the initiating function completes. [Note: In other words, the program is not required to guarantee the validity of the argument after the initiating function completes. —end note] The implementation may make copies of the argument, and all copies shall be destroyed no later than immediately after invocation of the completion handler.
[async.reqmts.async.non.blocking]
An initiating function shall not block (C++Std [defns.block]) the calling thread pending completion of the outstanding operation.
[Note: Initiating functions may still block the calling thread for other reasons. For example, an initiating function may lock a mutex in order to synchronize access to shared data. —end note]
[async.reqmts.async.assoc.exec]
Certain objects that participate in asynchronous operations have an associated executor. These are obtained as specified below.
              An asynchronous operation has an associated executor satisfying the
              Executor
              requirements. If not otherwise specified by the asynchronous operation,
              this associated executor is an object of type system_executor.
            
All asynchronous operations in this Technical Specification have an associated executor object that is determined as follows:
              — If the initiating function is a member function, the associated executor
              is that returned by the get_executor
              member function on the same object.
            
              — If the initiating function is not a member function, the associated
              executor is that returned by the get_executor
              member function of the first argument to the initiating function.
            
              Let Executor1 be the
              type of the associated executor. Let ex1
              be a value of type Executor1,
              representing the associated executor object obtained as described above.
            
[async.reqmts.async.handler.exec]
              A completion handler object of type CompletionHandler
              has an associated executor of type Executor2
              satisfying the Executor requirements.
              The type Executor2
              is associated_executor_t<CompletionHandler, Executor1>. Let ex2
              be a value of type Executor2
              obtained by performing get_associated_executor(completion_handler, ex1).
            
              The implementation of an asynchronous operation shall maintain an object
              work1 of type executor_work_guard<Executor1>,
              initialized with work1(ex1) and with work1.owns_work() == true, until the asynchronous operation
              has completed.
            
              The implementation of an asynchronous operation shall maintain an object
              work2 of type executor_work_guard<Executor2>,
              initialized with work2(ex2) and with work2.owns_work() == true, until the asynchronous operation
              has completed and completion_handler
              has been submitted for execution.
            
              Asynchronous operations may allocate memory. [Note:
              Such as a data structure to store copies of the completion_handler
              object and the initiating function's arguments. —end note]
            
              Let Alloc1 be a type,
              satisfying the ProtoAllocator requirements,
              that represents the asynchronous operation's default allocation strategy.
              [Note: Typically std::allocator<void>. —end note]
              Let alloc1 be a value
              of type Alloc1.
            
              A completion handler object of type CompletionHandler
              has an associated allocator object alloc2
              of type Alloc2 satisfying
              the ProtoAllocator
              requirements. The type Alloc2
              is associated_allocator_t<CompletionHandler, Alloc1>. Let alloc2
              be a value of type Alloc2
              obtained by performing get_associated_allocator(completion_handler, alloc1).
            
The asynchronous operations defined in this Technical Specification:
— If required, allocate memory using only the completion handler's associated allocator.
— Prior to completion handler execution, deallocate any memory allocated using the completion handler's associated allocator.
[Note: The implementation may perform operating system or underlying API calls that perform memory allocations not using the associated allocator. Invocations of the allocator functions may not introduce data races (See C++Std [res.on.data.races]). —end note]
[async.reqmts.async.completion]
              Let Args...
              be the argument types of the completion signature Signature
              and let N be sizeof...(Args).
              Let i be in the range [0,N).
              Let Ti be the ith
              type in Args...
              and let ti be the ith
              completion handler argument associated with Ti.
            
              Let f be a function
              object, callable as f(), that invokes completion_handler
              as if by completion_handler(forward<T0>(t0),
              ..., forward<TN-1>(tN-1)).
            
              If an asynchonous operation completes immediately (that is, within
              the thread of execution calling the initiating function, and before
              the initiating function returns), the completion handler shall be submitted
              for execution as if by performing ex2.post(std::move(f), alloc2). Otherwise, the completion handler
              shall be submitted for execution as if by performing ex2.dispatch(std::move(f), alloc2).
            
[async.reqmts.async.exceptions]
Completion handlers are permitted to throw exceptions. The effect of any exception propagated from the execution of a completion handler is determined by the executor which is executing the completion handler.
          The async_result class
          template is a customization point for asynchronous operations. Template
          parameter CompletionToken
          specifies the model used to obtain the result of the asynchronous operation.
          Template parameter Signature
          is the call signature (C++Std [func.def]) for the completion handler type
          invoked on completion of the asynchronous operation. The async_result template:
        
          — transforms a CompletionToken
          into a completion handler type that is based on a Signature;
          and
        
— determines the return type and return value of an asynchronous operation's initiating function.
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class CompletionToken, class Signature, class = void> class async_result { public: typedef CompletionToken completion_handler_type; typedef void return_type; explicit async_result(completion_handler_type&) {} async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; return_type get() {} }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The template parameter CompletionToken
          shall be an object type. The template parameter Signature
          shall be a call signature (C++Std [func.def]).
        
          Specializations of async_result
          shall satisfy the Destructible
          requirements (C++Std [destructible]) in addition to the requirements in
          the table below. In this table, R
          is a specialization of async_result;
          r is a modifiable lvalue
          of type R; and h is a modifiable lvalue of type R::completion_handler_type.
        
Table 6. async_result specialization requirements
| Expression | Return type | Requirement | 
|---|---|---|
| 
                     | 
                    A type satisfying  | |
| 
                     | 
                     | |
| 
                     | ||
| 
                     | 
                     | 
                    [Note: An asynchronous operation's initiating
                    function uses the  | 
          Class template async_completion
          is provided as a convenience, to simplify the implementation of asynchronous
          operations that use async_result.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class CompletionToken, class Signature> struct async_completion { typedef async_result<decay_t<CompletionToken>, Signature>::completion_handler_type completion_handler_type; explicit async_completion(CompletionToken& t); async_completion(const async_completion&) = delete; async_completion& operator=(const async_completion&) = delete; see below completion_handler; async_result<decay_t<CompletionToken>, Signature> result; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The template parameter Signature
          shall be a call signature (C++Std [func.def]).
        
explicit async_completion(CompletionToken& t);
Effects: If
CompletionTokenandcompletion_handler_typeare the same type, bindscompletion_handlertot; otherwise, initializescompletion_handlerwith the result offorward<CompletionToken>(t). Initializesresultwithcompletion_handler.
see below completion_handler;
Type:
completion_handler_type&ifCompletionTokenandcompletion_handler_typeare the same type; otherwise,completion_handler_type.
          Class template associated_allocator
          is an associator for the
          ProtoAllocator
          type requirements, with default candidate type allocator<void> and default candidate object allocator<void>().
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class ProtoAllocator = allocator<void>> struct associated_allocator { typedef see below type; static type get(const T& t, const ProtoAllocator& a = ProtoAllocator()) noexcept; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Specializations of associated_allocator
          shall satisfy the requirements in the table below. In this table, X is a specialization of associated_allocator for the template
          parameters T and ProtoAllocator; t
          is a value of (possibly const) T;
          and a is an object of type
          ProtoAllocator.
        
Table 7. associated_allocator specialization requirements
| Expression | Return type | Note | 
|---|---|---|
| 
                     | A type meeting the proto-allocator requirements. | |
| 
                     | 
                     | 
                    Shall not exit via an exception. | 
| 
                     | 
                     | Shall not exit via an exception. | 
typedef see below type;
Type: If
Thas a nested typeallocator_type,typename T::allocator_type. OtherwiseProtoAllocator.
type get(const T& t, const ProtoAllocator& a = ProtoAllocator()) noexcept;
Returns: If
Thas a nested typeallocator_type,t.get_allocator(). Otherwisea.
template<class T> associated_allocator_t<T> get_associated_allocator(const T& t) noexcept;
Returns:
associated_allocator<T>::get(t).
template<class T, class ProtoAllocator> associated_allocator_t<T, ProtoAllocator> get_associated_allocator(const T& t, const ProtoAllocator& a) noexcept;
Returns:
associated_allocator<T, ProtoAllocator>::get(t, a).
          Class execution_context
          implements an extensible, type-safe, polymorphic set of services, indexed
          by service type.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class execution_context { public: class service; // construct / copy / destroy: execution_context(); execution_context(const execution_context&) = delete; execution_context& operator=(const execution_context&) = delete; virtual ~execution_context(); // execution context operations: void notify_fork(fork_event e); protected: // execution context protected operations: void shutdown() noexcept; void destroy() noexcept; }; // service access: template<class Service> typename Service::key_type& use_service(execution_context& ctx); template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args); template<class Service> bool has_service(const execution_context& ctx) noexcept; class service_already_exists : public logic_error { }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Access to the services of an execution_context
          is via three function templates, use_service<>, make_service<> and has_service<>.
        
          In a call to use_service<Service>(), the type argument chooses a service.
          If the service is not present in an execution_context,
          an object of type Service
          is created and added to the execution_context.
          A program can check if an execution_context
          implements a particular service with the function template has_service<Service>().
        
          Service objects may be explicitly added to an execution_context
          using the function template make_service<Service>(). If the service is already present,
          make_service exits via
          an exception of type service_already_exists.
        
          Once a service reference is obtained from an execution_context
          object by calling use_service<>, that reference remains usable
          until a call to destroy().
        
execution_context();
Effects: Creates an object of class
execution_contextwhich contains no services. [Note: An implementation might preload services of internal service types for its own use. —end note]
~execution_context();
Effects: Destroys an object of class
execution_context. Performsshutdown()followed bydestroy().
void notify_fork(fork_event e);
Effects: For each service object
svcin the set:
— Ife == fork_event::prepare, performssvc->notify_fork(e)in reverse order of addition to the set.
— Otherwise, performssvc->notify_fork(e)in order of addition to the set.
void shutdown() noexcept;
Effects: For each service object
svcin theexecution_contextset, in reverse order of addition to the set, performssvc->shutdown(). For each service in the set,svc->shutdown()is called only once irrespective of the number of calls toshutdownon theexecution_context.
void destroy() noexcept;
Effects: Destroys each service object in the
execution_contextset, and removes it from the set, in reverse order of addition to the set.
            The functions use_service,
            make_service, and has_service do not introduce data races
            as a result of concurrent calls to those functions from different threads.
          
template<class Service> typename Service::key_type& use_service(execution_context& ctx);
Effects: If an object of type
Service::key_typedoes not already exist in theexecution_contextset identified byctx, creates an object of typeService, initialized asService(ctx), and adds it to the set.
Returns: A reference to the corresponding service of
ctx.
Notes: The reference returned remains valid until a call to
destroy.
template<class Service, class... Args> Service& make_service(execution_context& ctx, Args&&... args);
Requires: A service object of type
Service::key_typedoes not already exist in theexecution_contextset identified byctx.
Effects: Creates an object of type
Service, initialized asService(ctx, forward<Args>(args)...), and adds it to theexecution_contextset identified byctx.
Throws:
service_already_existsif a corresponding service object of typeKeyis already present in the set.
Notes: The reference returned remains valid until a call to
destroy.
template<class Service> bool has_service(const execution_context& ctx) noexcept;
Returns:
trueif an object of typeService::key_typeis present inctx, otherwisefalse.
namespace std { namespace experimental { namespace net { inline namespace v1 { class execution_context::service { protected: // construct / copy / destroy: explicit service(execution_context& owner); service(const service&) = delete; service& operator=(const service&) = delete; virtual ~service(); // service observers: execution_context& context() noexcept; private: // service operations: virtual void shutdown() noexcept = 0; virtual void notify_fork(fork_event e) {} execution_context& context_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std explicit service(execution_context& owner);
Postconditions:
std::addressof(context_) == std::addressof(owner).
execution_context& context() noexcept;
Returns:
context_.
          The class template is_executor
          can be used to detect executor types satisfying the Executor type requirements.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T> struct is_executor; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          T shall be a complete type.
        
          Class template is_executor
          is a UnaryTypeTrait (C++Std [meta.rqmts]) with a BaseCharacteristic of
          true_type if the type
          T meets the syntactic requirements
          for Executor,
          otherwise false_type.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { struct executor_arg_t { }; constexpr executor_arg_t executor_arg = executor_arg_t(); } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The executor_arg_t struct
          is an empty structure type used as a unique type to disambiguate constructor
          and function overloading. Specifically, types may have constructors with
          executor_arg_t as the first
          argument, immediately followed by an argument of a type that satisfies
          the Executor requirements.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Executor> struct uses_executor; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
            Remark: Detects whether T
            has a nested executor_type
            that is convertible from Executor.
            Meets the BinaryTypeTrait
            requirements (C++Std [meta.rqmts]). The implementation provides a definition
            that is derived from true_type
            if a type T::executor_type exists and is_convertible<Executor,
            T::executor_type>::value !=
            false, otherwise it is derived
            from false_type. A program
            may specialize this template to derive from true_type
            for a user-defined type T
            that does not have a nested executor_type
            but nonetheless can be constructed with an executor if the first argument
            of a constructor has type executor_arg_t
            and the second argument has type Executor.
          
            Uses-executor construction with executor Executor refers to the construction
            of an object obj of type
            T, using constructor
            arguments v1,
            v2,
            ..., vN
            of types V1,
            V2,
            ..., VN,
            respectively, and an executor ex
            of type Executor, according
            to the following rules:
          
            — if uses_executor<T, Executor>::value is true
            and is_constructible<T, executor_arg_t, Executor, V1, V2, ..., VN>::value is true,
            then obj is initialized
            as obj(executor_arg,
            ex,
            v1,
            v2,
            ..., vN);
          
            — otherwise, obj is initialized
            as obj(v1, v2, ..., vN).
          
          Class template associated_allocator
          is an associator for the
          Executor
          type requirements, with default candidate type system_executor
          and default candidate object system_executor().
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Executor = system_executor> struct associated_executor { typedef see below type; static type get(const T& t, const Executor& e = Executor()) noexcept; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Specializations of associated_executor
          shall satisfy the requirements in the table below. In this table, X is a specialization of associated_executor for the template
          parameters T and Executor; t
          is a value of (possibly const) T;
          and e is an object of type
          Executor.
        
Table 8. associated_executor specialization requirements
| Expression | Return type | Note | 
|---|---|---|
| 
                     | A type meeting Executor requirements. | |
| 
                     | 
                     | 
                    Shall not exit via an exception. | 
| 
                     | 
                     | Shall not exit via an exception. | 
typedef see below type;
Type: If
Thas a nested typeexecutor_type,typename T::executor_type. OtherwiseExecutor.
type get(const T& t, const Executor& e = Executor()) noexcept;
Returns: If
Thas a nested typeexecutor_type,t.get_executor(). Otherwisee.
template<class T> associated_executor_t<T> get_associated_executor(const T& t) noexcept;
Returns:
associated_executor<T>::get(t).
template<class T, class Executor> associated_executor_t<T, Executor> get_associated_executor(const T& t, const Executor& ex) noexcept;
Returns:
associated_executor<T, Executor>::get(t, ex).
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::valueistrue.
template<class T, class ExecutionContext> associated_executor_t<T, typename ExecutionContext::executor_type> get_associated_executor(const T& t, ExecutionContext& ctx) noexcept;
Returns:
get_associated_executor(t, ctx.get_executor()).
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::valueistrue.
          executor_binder<T, Executor> binds an executor of type Executor satisfying Executor
          requirements to an object or function of type T.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Executor> class executor_binder { public: // types: typedef T target_type; typedef Executor executor_type; // construct / copy / destroy: executor_binder(T t, const Executor& ex); executor_binder(const executor_binder& other) = default; executor_binder(executor_binder&& other) = default; template<class U, class OtherExecutor> executor_binder(const executor_binder<U, OtherExecutor>& other); template<class U, class OtherExecutor> executor_binder(executor_binder<U, OtherExecutor>&& other); template<class U, class OtherExecutor> executor_binder(executor_arg_t, const Executor& ex, const executor_binder<U, OtherExecutor>& other); template<class U, class OtherExecutor> executor_binder(executor_arg_t, const Executor& ex, executor_binder<U, OtherExecutor>&& other); ~executor_binder(); // executor binder access: T& get() noexcept; const T& get() const noexcept; executor_type get_executor() const noexcept; // executor binder invocation: template<class... Args> result_of_t<T&(Args&&...)> operator()(Args&&... args); template<class... Args> result_of_t<const T&(Args&&...)> operator()(Args&&... args) const; private: Executor ex_; // exposition only T target_; // exposition only }; template<class T, class Executor, class Signature> class async_result<executor_binder<T, Executor>, Signature>; template<class T, class Executor, class ProtoAllocator> struct associated_allocator<executor_binder<T, Executor>, ProtoAllocator>; template<class T, class Executor, class Executor1> struct associated_executor<executor_binder<T, Executor>, Executor1>; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
executor_binder(T t, const Executor& ex);
Effects: Initializes
ex_withex. Initializestarget_by performing uses-executor construction, using the constructor argumentstd::move(t)and the executorex_.
template<class U, class OtherExecutor> executor_binder(const executor_binder<U, OtherExecutor>& other);
Requires: If
Uis not convertible toT, or ifOtherExecutoris not convertible toExecutor, the program is ill-formed.
Effects: Initializes
ex_withother.get_executor(). Initializestarget_by performing uses-executor construction, using the constructor argumentother.get()and the executorex_.
template<class U, class OtherExecutor> executor_binder(executor_binder<U, OtherExecutor>&& other);
Requires: If
Uis not convertible toT, or ifOtherExecutoris not convertible toExecutor, the program is ill-formed.
Effects: Initializes
ex_withother.get_executor(). Initializestarget_by performing uses-executor construction, using the constructor argumentstd::move(other.get())and the executorex_.
template<class U, class OtherExecutor> executor_binder(executor_arg_t, const Executor& ex, const executor_binder<U, OtherExecutor>& other);
Requires: If
Uis not convertible toTthe program is ill-formed.
Effects: Initializes
ex_withex. Initializestarget_by performing uses-executor construction, using the constructor argumentother.get()and the executorex_.
template<class U, class OtherExecutor> executor_binder(executor_arg_t, const Executor& ex, executor_binder<U, OtherExecutor>&& other);
Requires:
UisTor convertible toT.
Effects: Initializes
ex_withex. Initializestarget_by performing uses-executor construction, using the constructor argumentstd::move(other.get())and the executorex_.
T& get() noexcept; const T& get() const noexcept;
Returns:
target_.
executor_type get_executor() const noexcept;
Returns:
executor_.
[async.exec.binder.invocation]
template<class... Args> result_of_t<T&(Args&&...)> operator()(Args&&... args); template<class... Args> result_of_t<const T&(Args&&...)> operator()(Args&&... args) const;
Returns:
INVOKE(get(), forward<Args>(args)...)(C++Std [func.require]).
[async.exec.binder.async.result]
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Executor, class Signature> class async_result<executor_binder<T, Executor>, Signature> { public: typedef executor_binder< typename async_result<T, Signature>::completion_handler_type, Executor> completion_handler_type; typedef typename async_result<T, Signature>::return_type return_type; explicit async_result(completion_handler_type& h); async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; return_type get(); private: async_result<T, Signature> target_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std explicit async_result(completion_handler_type& h);
Effects: Initializes
target_astarget_(h.get()).
return_type get();
Returns:
target_.get().
[async.exec.binder.assoc.alloc]
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Executor, class ProtoAllocator> struct associated_allocator<executor_binder<T, Executor>, ProtoAllocator> { typedef associated_allocator_t<T, ProtoAllocator> type; static type get(const executor_binder<T, Executor>& b, const ProtoAllocator& a = ProtoAllocator()) noexcept; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std static type get(const executor_binder<T, Executor>& b, const ProtoAllocator& a = ProtoAllocator()) noexcept;
Returns:
associated_allocator<T, ProtoAllocator>::get(b.get(), a).
[async.exec.binder.assoc.exec]
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Executor, class Executor1> struct associated_executor<executor_binder<T, Executor>, Executor1> { typedef Executor type; static type get(const executor_binder<T, Executor>& b, const Executor1& e = Executor1()) noexcept; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std static type get(const executor_binder<T, Executor>& b, const Executor1& e = Executor1()) noexcept;
Returns:
b.get_executor().
template<class Executor, class T> executor_binder<decay_t<T>, Executor> bind_executor(const Executor& ex, T&& t);
Returns:
executor_binder<decay_t<T>, Executor>(forward<T>(t), ex).
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::valueistrue.
template<class ExecutionContext, class CompletionToken> executor_binder<decay_t<T>, typename ExecutionContext::executor_type> bind_executor(ExecutionContext& ctx, T&& t);
Returns:
bind_executor(ctx.get_executor(), forward<T>(t)).
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::valueistrue.
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Executor> class executor_work_guard { public: // types: typedef Executor executor_type; // construct / copy / destroy: explicit executor_work_guard(const executor_type& ex) noexcept; executor_work_guard(const executor_work_guard& other) noexcept; executor_work_guard(executor_work_guard&& other) noexcept; executor_work_guard& operator=(const executor_work_guard&) = delete; ~executor_work_guard(); // executor work guard observers: executor_type get_executor() const noexcept; bool owns_work() const noexcept; // executor work guard modifiers: void reset() noexcept; private: Executor ex_; // exposition only bool owns_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
[async.exec.work.guard.members]
explicit executor_work_guard(const executor_type& ex) noexcept;
Effects: Initializes
ex_withex, and then performsex_.on_work_started().
Postconditions:
ex == ex_andowns_ == true.
executor_work_guard(const executor_work_guard& other) noexcept;
Effects: Initializes
ex_withother.ex_. Ifother.owns_ == true, performsex_.on_work_started().
Postconditions:
ex_ == other.ex_andowns_ == other.owns_.
executor_work_guard(executor_work_guard&& other) noexcept;
Effects: Initializes
ex_withstd::move(other.ex_)andowns_withother.owns_, and setsother.owns_tofalse.
~executor_work_guard();
Effects: If
owns_istrue, performsex_.on_work_finished().
executor_type get_executor() const noexcept;
Returns:
ex_.
bool owns_work() const noexcept;
Returns:
owns_.
void reset() noexcept;
Effects: If
owns_istrue, performsex_.on_work_finished().
Postconditions:
owns_ == false.
template<class Executor> executor_work_guard<Executor> make_work_guard(const Executor& ex);
Returns:
executor_work_guard<Executor>(ex).
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::valueistrue.
template<class ExecutionContext> executor_work_guard<typename ExecutionContext::executor_type> make_work_guard(ExecutionContext& ctx);
Returns:
make_work_guard(ctx.get_executor()).
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::valueistrue.
template<class T> executor_work_guard<associated_executor_t<T>> make_work_guard(const T& t);
Returns:
make_work_guard(get_associated_executor(t)).
Remarks: This function shall not participate in overload resolution unless
is_executor<T>::valueisfalseandis_convertible<T&, execution_context&>::valueisfalse.
template<class T, class U> auto make_work_guard(const T& t, U&& u) -> decltype(make_work_guard(get_associated_executor(t, forward<U>(u))));
Returns:
make_work_guard(get_associated_executor(t, forward<U>(u))).
          Class system_executor represents
          a set of rules where function objects are permitted to execute on any thread.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class system_executor { public: // constructors: system_executor() {} // executor operations: system_context& context() noexcept; void on_work_started() noexcept {} void on_work_finished() noexcept {} template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a); }; bool operator==(const system_executor&, const system_executor&) noexcept; bool operator!=(const system_executor&, const system_executor&) noexcept; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Class system_executor satisfies
          the Destructible (C++Std
          [destructible]), DefaultConstructible
          (C++Std [defaultconstructible]), and Executor type requirements.
        
          To satisfy the Executor
          requirements for the post
          and defer member functions,
          the system executor may create thread
          objects to run the submitted function objects. These thread
          objects are collectively referred to as system threads.
        
system_context& context() noexcept;
Returns: A reference to an object with static storage duration. All calls to this function return references to the same object.
template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a);
Effects: Equivalent to
DECAY_COPY(forward<Func>(f))()(C++Std [thread.decaycopy]).
template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a);
Effects: If
context().stopped() == false, creates an objectf1initialized withDECAY_COPY(forward<Func>(f)), and callsf1as if in a thread of execution represented by athreadobject. Any exception propagated from the execution ofDECAY_COPY(forward<Func>(f))()results in a call tostd::terminate.
[async.system.exec.comparisons]
bool operator==(const system_executor&, const system_executor&) noexcept;
Returns:
true.
bool operator!=(const system_executor&, const system_executor&) noexcept;
Returns:
false.
          Class system_context implements
          the execution context associated with system_executor
          objects.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class system_context : public execution_context { public: // types: typedef system_executor executor_type; // construct / copy / destroy: system_context() = delete; system_context(const system_context&) = delete; system_context& operator=(const system_context&) = delete; ~system_context(); // system_context operations: executor_type get_executor() noexcept; void stop(); bool stopped() const noexcept; void join(); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The class system_context
          satisfies the ExecutionContext type requirements.
        
          The system_context member
          functions get_executor,
          stop, and stopped, and the system_executor
          copy constructors, member functions and comparison operators, do not introduce
          data races as a result of concurrent calls to those functions from different
          threads of execution.
        
~system_context();
Effects: Performs
stop()followed byjoin().
executor_type get_executor() noexcept;
Returns:
system_executor().
void stop();
Effects: Signals all system threads to exit as soon as possible. If a system thread is currently executing a function object, the thread will exit only after completion of that function object. Returns without waiting for the system threads to complete.
Postconditions:
stopped() == true.
bool stopped() const noexcept;
Returns:
trueif thesystem_contexthas been stopped by a prior call tostop.
void join();
Effects: Blocks the calling thread (C++Std [defns.block]) until all system threads have completed.
Synchronization: The completion of each system thread synchronizes with (C++Std [intro.multithread]) the corresponding successful
join()return.
          An exception of type bad_executor
          is thrown by executor member
          functions dispatch, post, and defer
          when the executor object has no target.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class bad_executor : public exception { public: // constructor: bad_executor() noexcept; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std bad_executor() noexcept;
Effects: constructs a
bad_executorobject.
Postconditions:
what()returns an implementation-defined NTBS.
          The executor class provides
          a polymorphic wrapper for types that satisfy the Executor
          requirements.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class executor { public: // construct / copy / destroy: executor() noexcept; executor(nullptr_t) noexcept; executor(const executor& e) noexcept; executor(executor&& e) noexcept; template<class Executor> executor(Executor e); template<class Executor, class ProtoAllocator> executor(allocator_arg_t, const ProtoAllocator& a, Executor e); executor& operator=(const executor& e) noexcept; executor& operator=(executor&& e) noexcept; executor& operator=(nullptr_t) noexcept; template<class Executor> executor& operator=(Executor e); ~executor(); // executor modifiers: void swap(executor& other) noexcept; template<class Executor, class ProtoAllocator> void assign(Executor e, const ProtoAllocator& a); // executor operations: execution_context& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a); // executor capacity: explicit operator bool() const noexcept; // executor target access: const type_info& target_type() const noexcept; template<class Executor> Executor* target() noexcept; template<class Executor> const Executor* target() const noexcept; }; template<> struct is_executor<executor> : true_type {}; // executor comparisons: bool operator==(const executor& a, const executor& b) noexcept; bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept; bool operator!=(const executor& a, const executor& b) noexcept; bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept; // executor specialized algorithms: void swap(executor& a, executor& b) noexcept; } // inline namespace v1 } // namespace net } // namespace experimental template<class Allocator> struct uses_allocator<experimental::net::v1::executor, Allocator> : true_type {}; } // namespace std
          Class executor meets the
          requirements of Executor,
          DefaultConstructible (C++Std
          [defaultconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
          [Note: To meet the noexcept
          requirements for executor copy constructors and move constructors, implementations
          may share a target between two or more executor
          objects. —end note]
        
The target is the executor object that is held by the wrapper.
executor() noexcept;
Postconditions:
!*this.
executor(nullptr_t) noexcept;
Postconditions:
!*this.
executor(const executor& e) noexcept;
Postconditions:
!*thisif!e; otherwise,*thistargetse.target()or a copy ofe.target().
executor(executor&& e) noexcept;
Effects: If
!e,*thishas no target; otherwise, movese.target()or move-constructs the target ofeinto the target of*this, leavingein a valid state with an unspecified value.
template<class Executor> executor(Executor e);
Effects:
*thistargets a copy ofeinitialized withstd::move(e).
template<class Executor, class ProtoAllocator> executor(allocator_arg_t, const ProtoAllocator& a, Executor e);
Effects:
*thistargets a copy ofeinitialized withstd::move(e).
A copy of the allocator argument is used to allocate memory, if necessary, for the internal data structures of the constructed
executorobject.
executor& operator=(const executor& e) noexcept;
Effects:
executor(e).swap(*this).
Returns:
*this.
executor& operator=(executor&& e) noexcept;
Effects: Replaces the target of
*thiswith the target ofe, leavingein a valid state with an unspecified value.
Returns:
*this.
executor& operator=(nullptr_t) noexcept;
Effects:
executor(nullptr).swap(*this).
Returns:
*this.
template<class Executor> executor& operator=(Executor e);
Effects:
executor(std::move(e)).swap(*this).
Returns:
*this.
~executor();
Effects: If
*this != nullptr, releases shared ownership of, or destroys, the target of*this.
void swap(executor& other) noexcept;
Effects: Interchanges the targets of
*thisandother.
template<class Executor, class ProtoAllocator> void assign(Executor e, const ProtoAllocator& a);
Effects:
executor(allocator_arg, a, std::move(e)).swap(*this).
execution_context& context() noexcept;
Requires:
*this != nullptr.
Returns:
e.context(), whereeis the target object of*this.
void on_work_started() noexcept;
Requires:
*this != nullptr.
Effects:
e.on_work_started(), whereeis the target object of*this.
void on_work_finished() noexcept;
Requires:
*this != nullptr.
Effects:
e.on_work_finished(), whereeis the target object of*this.
template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a);
Let
ebe the target object of*this. Leta1be the allocator that was specified when the target was set. Letfdbe the result ofDECAY_COPY(f)(C++Std [thread.decaycopy]).
Effects:
e.dispatch(g, a1), wheregis a function object of unspecified type that, when called asg(), performsfd(). The allocatorais used to allocate any memory required to implementg.
template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a);
Let
ebe the target object of*this. Leta1be the allocator that was specified when the target was set. Letfdbe the result ofDECAY_COPY(f).
Effects:
e.post(g, a1), wheregis a function object of unspecified type that, when called asg(), performsfd(). The allocatorais used to allocate any memory required to implementg.
template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a);
Let
ebe the target object of*this. Leta1be the allocator that was specified when the target was set. Letfdbe the result ofDECAY_COPY(f).
Effects:
e.defer(g, a1), wheregis a function object of unspecified type that, when called asg(), performsfd(). The allocatorais used to allocate any memory required to implementg.
explicit operator bool() const noexcept;
Returns:
trueif*thishas a target, otherwisefalse.
const type_info& target_type() const noexcept;
Returns: If
*thishas a target of typeT,typeid(T); otherwise,typeid(void).
template<class Executor> Executor* target() noexcept; template<class Executor> const Executor* target() const noexcept;
Returns: If
target_type() == typeid(Executor)a pointer to the stored executor target; otherwise a null pointer value.
bool operator==(const executor& a, const executor& b) noexcept;
Returns:
—trueif!aand!b;
—trueifaandbshare a target;
—trueifeandfare the same type ande == f, whereeis the target ofaandfis the target ofb;
— otherwisefalse.
bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept;
Returns:
!e.
bool operator!=(const executor& a, const executor& b) noexcept;
Returns:
!(a == b).
bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept;
Returns:
(bool) e.
void swap(executor& a, executor& b) noexcept;
Effects:
a.swap(b).
template<class CompletionToken> DEDUCED dispatch(CompletionToken&& token);
Effects:
— Constructs an objectcompletionof typeasync_completion<CompletionToken, void()>, initialized withforward<CompletionToken>(token).
— Performsex.dispatch(std::move(completion.completion_handler), alloc), whereexis the result ofget_associated_executor(completion.completion_handler), andallocis the result ofget_associated_allocator(completion.completion_handler).
Returns:
completion.result.get().
template<class Executor, class CompletionToken> DEDUCED dispatch(const Executor& ex, CompletionToken&& token);
Effects:
— Constructs an objectcompletionof typeasync_completion<CompletionToken, void()>, initialized withforward<CompletionToken>(token).
— Constructs a function objectfcontaining as members:
• a copy of the completion handlerh, initialized withstd::move(completion.completion_handler),
• anexecutor_work_guardobjectwfor the completion handler's associated executor, initialized withmake_work_guard(h),
and where the effect off()is:
•w.get_executor().dispatch(std::move(h), alloc), whereallocis the result ofget_associated_allocator(h), followed by
•w.reset().
— Performsex.dispatch(std::move(f), alloc), whereallocis the result ofget_associated_allocator(completion.completion_handler)prior to the construction off.
Returns:
completion.result.get().
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::valueistrue.
template<class ExecutionContext, class CompletionToken> DEDUCED dispatch(ExecutionContext& ctx, CompletionToken&& token);
Returns:
std::experimental::net::dispatch(ctx.get_executor(), forward<CompletionToken>(token)).
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::valueistrue.
          [Note: The function post
          satisfies the requirements for an asynchronous
          operation. —end note]
        
template<class CompletionToken> DEDUCED post(CompletionToken&& token);
Effects:
— Constructs an objectcompletionof typeasync_completion<CompletionToken, void()>, initialized withforward<CompletionToken>(token).
— Performsex.post(std::move(completion.completion_handler), alloc), whereexis the result ofget_associated_executor(completion.completion_handler), andallocis the result ofget_associated_allocator(completion.completion_handler).
Returns:
completion.result.get().
template<class Executor, class CompletionToken> DEDUCED post(const Executor& ex, CompletionToken&& token);
Effects:
— Constructs an objectcompletionof typeasync_completion<CompletionToken, void()>, initialized withforward<CompletionToken>(token).
— Constructs a function objectfcontaining as members:
• a copy of the completion handlerh, initialized withstd::move(completion.completion_handler),
• anexecutor_work_guardobjectwfor the completion handler's associated executor, initialized withmake_work_guard(h),
and where the effect off()is:
•w.get_executor().dispatch(std::move(h), alloc), whereallocis the result ofget_associated_allocator(h), followed by
•w.reset().
— Performsex.post(std::move(f), alloc), whereallocis the result ofget_associated_allocator(completion.completion_handler)prior to the construction off.
Returns:
completion.result.get().
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::valueistrue.
template<class ExecutionContext, class CompletionToken> DEDUCED post(ExecutionContext& ctx, CompletionToken&& token);
Returns:
std::experimental::net::post(ctx.get_executor(), forward<CompletionToken>(token)).
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::valueistrue.
template<class CompletionToken> DEDUCED defer(CompletionToken&& token);
Effects:
— Constructs an objectcompletionof typeasync_completion<CompletionToken, void()>, initialized withforward<CompletionToken>(token).
— Performsex.defer(std::move(completion.completion_handler), alloc), whereexis the result ofget_associated_executor(completion.completion_handler), andallocis the result ofget_associated_allocator(completion.completion_handler).
Returns:
completion.result.get().
template<class Executor, class CompletionToken> DEDUCED defer(const Executor& ex, CompletionToken&& token);
Effects:
— Constructs an objectcompletionof typeasync_completion<CompletionToken, void()>, initialized withforward<CompletionToken>(token).
— Constructs a function objectfcontaining as members:
• a copy of the completion handlerh, initialized withstd::move(completion.completion_handler),
• anexecutor_work_guardobjectwfor the completion handler's associated executor, initialized withmake_work_guard(h),
and where the effect off()is:
•w.get_executor().dispatch(std::move(h), alloc), whereallocis the result ofget_associated_allocator(h), followed by
•w.reset().
— Performsex.defer(std::move(f), alloc), whereallocis the result ofget_associated_allocator(completion.completion_handler)prior to the construction off.
Returns:
completion.result.get().
Remarks: This function shall not participate in overload resolution unless
is_executor<Executor>::valueistrue.
template<class ExecutionContext, class CompletionToken> DEDUCED defer(ExecutionContext& ctx, CompletionToken&& token);
Returns:
std::experimental::net::defer(ctx.get_executor(), forward<CompletionToken>(token)).
Remarks: This function shall not participate in overload resolution unless
is_convertible<ExecutionContext&, execution_context&>::valueistrue.
          The class template strand
          is a wrapper around an object of type Executor
          satisfying the Executor requirements.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Executor> class strand { public: // types: typedef Executor inner_executor_type; // construct / copy / destroy: strand(); explicit strand(Executor ex); template<class ProtoAllocator> strand(allocator_arg_t, const ProtoAllocator& alloc, Executor ex); strand(const strand& other) noexcept; strand(strand&& other) noexcept; template<class OtherExecutor> strand(const strand<OtherExecutor>& other) noexcept; template<class OtherExecutor> strand(strand<OtherExecutor>&& other) noexcept; strand& operator=(const strand& other) noexcept; strand& operator=(strand&& other) noexcept; template<class OtherExecutor> strand& operator=(const strand<OtherExecutor>& other) noexcept; template<class OtherExecutor> strand& operator=(strand<OtherExecutor>&& other) noexcept; ~strand(); // strand operations: inner_executor_type get_inner_executor() const noexcept; bool running_in_this_thread() const noexcept; execution_context& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a); private: Executor inner_ex_; // exposition only }; bool operator==(const strand<Executor>& a, const strand<Executor>& b); bool operator!=(const strand<Executor>& a, const strand<Executor>& b); } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          strand<Executor>
          satisfies the Executor
          requirements.
        
A strand provides guarantees of ordering and non-concurrency. Given:
          — strand objects s1 and
          s2 such that s1 == s2
        
          — a function object f1 added
          to the strand s1 using
          post or defer,
          or using dispatch when
          s1.running_in_this_thread()
          == false
        
          — a function object f2 added
          to the strand s2 using
          post or defer,
          or using dispatch when
          s2.running_in_this_thread()
          == false
        
          then the implementation invokes f1
          and f2 such that:
        
          — the invocation of f1 is
          not concurrent with the invocation of f2
        
          — the invocation of f1 synchronizes
          with the invocation of f2.
        
          Furthermore, if the addition of f1
          happens before the addition of f2,
          then the invocation of f1
          happens before the invocation of f2.
        
          All member functions, except for the assignment operators and the destructor,
          do not introduce data races on *this, including its ordered, non-concurrent
          state. Additionally, constructors and assignment operators do not introduce
          data races on lvalue arguments.
        
          If any function f executed
          by the strand throws an exception, the subsequent strand state is as if
          f had exited without throwing
          an exception.
        
strand();
Effects: Constructs an object of class
strand<Executor>that represents a unique ordered, non-concurrent state. Initializesinner_ex_withinner_ex_().
Remarks: This overload shall not participate in overload resolution unless
Executorsatisfies theDefaultConstructiblerequirements (C++Std [defaultconstructible]).
explicit strand(Executor ex);
Effects: Constructs an object of class
strand<Executor>that represents a unique ordered, non-concurrent state. Initializesinner_ex_asinner_ex_(ex).
template<class ProtoAllocator> strand(allocator_arg_t, const ProtoAllocator& a, Executor ex);
Effects: Constructs an object of class
strand<Executor>that represents a unique ordered, non-concurrent state. Initializesinner_ex_asinner_ex_(ex). A copy of the allocator argumentais used to allocate memory, if necessary, for the internal data structures of the constructed strand object.
strand(const strand& other) noexcept;
Effects: Initializes
inner_ex_asinner_ex_(other.inner_ex_).
Postconditions:
—*this == other
—get_inner_executor() == other.get_inner_executor()
strand(strand&& other) noexcept;
Effects: Initializes
inner_ex_withinner_ex_(std::move(other.inner_ex_)).
Postconditions:
—*thisis equal to the prior value ofother
—get_inner_executor() == other.get_inner_executor()
template<class OtherExecutor> strand(const strand<OtherExecutor>& other) noexcept;
Requires:
OtherExecutoris convertible toExecutor.
Effects: Initializes
inner_ex_withinner_ex_(other.inner_ex_).
Postconditions:
*this == other.
template<class OtherExecutor> strand(strand<OtherExecutor>&& other) noexcept;
Requires:
OtherExecutoris convertible toExecutor.
Effects: Initializes
inner_ex_withinner_ex_(std::move(other.inner_ex_)).
Postconditions:
*thisis equal to the prior value ofother.
strand& operator=(const strand& other) noexcept;
Requires:
ExecutorisCopyAssignable(C++Std [copyassignable]).
Postconditions:
—*this == other
—get_inner_executor() == other.get_inner_executor()
Returns:
*this.
strand& operator=(strand&& other) noexcept;
Requires:
ExecutorisMoveAssignable(C++Std [moveassignable]).
Postconditions:
—*thisis equal to the prior value ofother
—get_inner_executor() == other.get_inner_executor()
Returns:
*this.
template<class OtherExecutor> strand& operator=(const strand<OtherExecutor>& other) noexcept;
Requires:
OtherExecutoris convertible toExecutor.ExecutorisCopyAssignable(C++Std [copyassignable]).
Effects: Assigns
other.inner_ex_toinner_ex_.
Postconditions:
*this == other.
Returns:
*this.
template<class OtherExecutor> strand& operator=(strand<OtherExecutor>&& other) noexcept;
Requires:
OtherExecutoris convertible toExecutor.ExecutorisMoveAssignable(C++Std [moveassignable]).
Effects: Assigns
std::move(other.inner_ex_)toinner_ex_.
Postconditions:
*thisis equal to the prior value ofother.
Returns:
*this.
~strand();
Effects: Destroys an object of class
strand<Executor>. After this destructor completes, objects that were added to the strand but have not yet been executed will be executed in a way that meets the guarantees of ordering and non-concurrency.
inner_executor_type get_inner_executor() const noexcept;
Returns:
inner_ex_.
bool running_in_this_thread() const noexcept;
Returns:
trueif the current thread of execution is running a function that was submitted to the strand, or to any other strand objectssuch thats == *this, usingdispatch,postordefer; otherwisefalse. [Note: That is, the current thread of execution's call chain includes a function that was submitted to the strand. —end note]
execution_context& context() noexcept;
Returns:
inner_ex_.context().
void on_work_started() noexcept;
Effects: Calls
inner_ex_.on_work_started().
void on_work_finished() noexcept;
Effects: Calls
inner_ex_.on_work_finished().
template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a);
Effects: If
running_in_this_thread() == true, callsDECAY_COPY(forward<Func>(f))()(C++Std [thread.decaycopy]). [Note: Iffexits via an exception, the exception propagates to the caller ofdispatch(). —end note] Otherwise, requests invocation off, as if by forwarding the function objectfand allocatorato the executorinner_ex_, such that the guarantees of ordering and non-concurrency are met.
template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a);
Effects: Requests invocation of
f, as if by forwarding the function objectfand allocatorato the executorinner_ex_, such that the guarantees of ordering and non-concurrency are met.
template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a);
Effects: Requests invocation of
f, as if by forwarding the function objectfand allocatorato the executorinner_ex_, such that the guarantees of ordering and non-concurrency are met.
bool operator==(const strand<Executor>& a, const strand<Executor>& b);
Returns:
true, if the strand objects share the same ordered, non-concurrent state; otherwisefalse.
bool operator!=(const strand<Executor>& a, const strand<Executor>& b);
Returns:
!(a == b).
          The class template use_future_t
          defines a set of types that, when passed as a completion
          token to an asynchronous operation's initiating function, cause
          the result of the asynchronous operation to be delivered via a future (C++Std
          [futures.unique_future]).
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class ProtoAllocator = allocator<void>> class use_future_t { public: // use_future_t types: typedef ProtoAllocator allocator_type; // use_future_t members: constexpr use_future_t() noexcept; explicit use_future_t(const allocator_type& a) noexcept; template<class OtherProtoAllocator> use_future_t<OtherProtoAllocator> rebind(const OtherProtoAllocator& a) const noexcept; allocator_type get_allocator() const noexcept; template <class F> unspecified operator()(F&& f) const; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
constexpr use_future_t() noexcept;
Effects: Constructs a
use_future_twith a default-constructed allocator.
explicit use_future_t(const allocator_type& a) noexcept;
Postconditions:
get_allocator() == a.
template<class OtherProtoAllocator> use_future_t<OtherProtoAllocator> rebind(const OtherProtoAllocator& a) const noexcept;
Returns: A
use_future_tobject whereget_allocator() == a.
allocator_type get_allocator() const noexcept;
Returns: The associated allocator object.
template <class F> unspecified operator()(F&& f) const;
Let
Tbe a completion token type. LetHbe a completion handler type and lethbe an object of typeH. LetFDbe the typedecay_t<F>and letfdbe an lvalue of typeFDconstructed withforward<F>(f). LetArgs...by the completion signature ofHand letNbesizeof...(Args). Letibe in the range [0,N) and letAibe theith type inArgs. Letaibe theith argument associated withAi.
Returns: A completion token
tof typeT.
Remarks: The return type
Tsatisfies theDestructible(C++Std [destructible]) andMoveConstructible(C++Std [moveconstructible]) requirements.
The object
hof typeHis an asynchronous provider with an associated shared state (C++Std [futures.state]). The effect ofh(is to atomically store the result ofa0, ...,aN-1)INVOKE(fd, forward<(C++Std [func.require]) in the shared state and make the shared state ready. IfA0>(a0), ..., forward<AN-1>(aN-1))fdexits via an exception then that exception is atomically stored in the shared state and the shared state is made ready.
The implementation provides a partial specialization
template <class Result, class... Args> async_result<T, Result(Args...)>such that:
— the nested typedefcompletion_handler_typeis a typeH;
— the nested typedefreturn_typeisfuture<result_of_t<FD(decay_t<Args>...)>>; and
— when an objectr1of typeasync_result<T, Result(Args...)>is constructed fromh, the expressionr1.get()returns a future with the same shared state ash.
For any executor type
E, the associated object for the associatorassociated_executor<H, E>is an executor where, for function objects executed using the executor'sdispatch(),post()ordefer()functions, any exception thrown is caught by a function object and stored in the associated shared state.
template<class ProtoAllocator, class Result, class... Args> class async_result<use_future_t<ProtoAllocator>, Result(Args...)> { typedef see below completion_handler_type; typedef see below return_type; explicit async_result(completion_handler_type& h); async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; return_type get(); };
            Let R be the type async_result<use_future_t<ProtoAllocator>,
            Result(Args...)>.
            Let F be the nested function
            object type R::completion_handler_type.
          
            An object t1 of type
            F is an asynchronous
            provider with an associated shared state (C++Std [futures.state]). The
            type F provides F::operator()
            such that the expression t1(declval<Args>()...) is well formed.
          
            The implementation specializes associated_executor
            for F. For function objects
            executed using the associated executor's dispatch(), post() or defer() functions, any exception thrown is
            caught by the executor and stored in the associated shared state.
          
            For any executor type E,
            the associated object for the associator associated_executor<F, E> is an executor where, for function
            objects executed using the executor's dispatch(), post() or defer() functions, any exception thrown by
            a function object is caught by the executor and stored in the associated
            shared state.
          
            When an object r1 of
            type R is constructed
            from t1, the expression
            r1.get()
            returns a future with the same shared state as t1.
          
            The type of R::return_type and the effects of F::operator()
            are defined in the table below. After establishing these effects, F::operator()
            makes the shared state ready. In this table, N is
            the value of sizeof...(Args);
            let i be in the range [0,N)
            and let Ti be the ith
            type in Args; let Ui
            be decay_t<Ti> for each
            type Ti in Args;
            let Ai be the deduced type of
            the ith argument to F::operator();
            and let ai be the ith
            argument to F::operator().
          
Table 9. async_result<use_future_t<ProtoAllocator>, Result(Args...)> semantics
| 
                       | 
                       | 
                       | 
                       | 
|---|---|---|---|
| 0 | 
                       | None. | |
| 1 | 
                       | 
                       | 
                      If  | 
| 1 | 
                       | 
                       | 
                      If  | 
| 1 | all other types | 
                       | 
                      Atomically stores  | 
| 2 | 
                       | 
                       | 
                      If  | 
| 2 | 
                       | 
                       | 
                      If  | 
| 2 | all other types | 
                       | 
                      Atomically stores  | 
| >2 | 
                       | 
                       | 
                      If  | 
| >2 | 
                       | 
                       | 
                      If  | 
| >2 | all other types | 
                       | 
                      Atomically stores  | 
[async.packaged.task.specializations]
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Result, class... Args, class Signature> class async_result<packaged_task<Result(Args...)>, Signature> { public: typedef packaged_task<Result(Args...)> completion_handler_type; typedef future<Result> return_type; explicit async_result(completion_handler_type& h); async_result(const async_result&) = delete; async_result& operator=(const async_result&) = delete; return_type get(); private: return_type future_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std explicit async_result(completion_handler_type& h);
Effects: Initializes
future_withh.get_future().
return_type get();
Returns:
std::move(future_).
namespace std { namespace experimental { namespace net { inline namespace v1 { class io_context; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
namespace std { namespace experimental { namespace net { inline namespace v1 { class io_context : public execution_context { public: // types: class executor_type; typedef implementation defined count_type; // construct / copy / destroy: io_context(); explicit io_context(int concurrency_hint); io_context(const io_context&) = delete; io_context& operator=(const io_context&) = delete; // io_context operations: executor_type get_executor() noexcept; count_type run(); template<class Rep, class Period> count_type run_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> count_type run_until(const chrono::time_point<Clock, Duration>& abs_time); count_type run_one(); template<class Rep, class Period> count_type run_one_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> count_type run_one_until(const chrono::time_point<Clock, Duration>& abs_time); count_type poll(); count_type poll_one(); void stop(); bool stopped() const noexcept; void restart(); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The class io_context satisfies
          the ExecutionContext type
          requirements.
        
          count_type is an implementation-defined
          unsigned integral type of at least 32 bits.
        
          The io_context member functions
          run, run_for,
          run_until, run_one, run_one_for,
          run_one_until, poll, and poll_one
          are collectively referred to as the run functions.
          The run functions must be called for the io_context
          to perform asynchronous
          operations on behalf of a C++ program. Notification that an asynchronous
          operation has completed is delivered by execution of the associated completion
          handler function object, as determined by the requirements for asynchronous
          operations.
        
          For an object of type io_context,
          outstanding work is defined as the sum of:
        
          — the total number of calls to the on_work_started
          function, less the total number of calls to the on_work_finished
          function, to any executor of the io_context.
        
          — the number of function objects that have been added to the io_context via any executor of the io_context, but not yet executed; and
        
          — the number of function objects that are currently being executed by the
          io_context.
        
          If at any time the outstanding work falls to 0,
          the io_context is stopped
          as if by stop().
        
          The io_context member functions
          get_executor, stop, and stopped,
          the run functions, and the io_context::executor_type
          copy constructors, member functions and comparison operators, do not introduce
          data races as a result of concurrent calls to those functions from different
          threads of execution. [Note: The restart
          member function is excluded from these thread safety requirements. —end
          note]
        
[io_context.io_context.members]
io_context(); explicit io_context(int concurrency_hint);
Effects: Creates an object of class
io_context.
Remarks: The
concurrency_hintparameter is a suggestion to the implementation on the number of threads that should process asynchronous operations and execute function objects.
executor_type get_executor() noexcept;
Returns: An executor that may be used for submitting function objects to the
io_context.
count_type run();
Requires: Must not be called from a thread that is currently calling a run function.
Effects: Equivalent to:
count_type n = 0; while (run_one()) if (n != numeric_limits<count_type>::max()) ++n;
Returns:
n.
template<class Rep, class Period> count_type run_for(const chrono::duration<Rep, Period>& rel_time);
Effects: Equivalent to:
return run_until(chrono::steady_clock::now() + rel_time);
template<class Clock, class Duration> count_type run_until(const chrono::time_point<Clock, Duration>& abs_time);
Effects: Equivalent to:
count_type n = 0; while (run_one_until(abs_time)) if (n != numeric_limits<count_type>::max()) ++n;
Returns:
n.
count_type run_one();
Requires: Must not be called from a thread that is currently calling a run function.
Effects: If the
io_contextobject has no outstanding work, performsstop(). Otherwise, blocks while the io_context has outstanding work, or until theio_contextis stopped, or until one function object has been executed.
If an executed function object throws an exception, the exception propagates to the caller of
run_one(). Theio_contextstate is as if the function object had returned normally.
Returns:
1if a function object was executed, otherwise0.
Notes: This function may invoke additional function objects through nested calls to the
io_contextexecutor'sdispatchmember function. These do not count towards the return value.
template<class Rep, class Period> count_type run_one_for(const chrono::duration<Rep, Period>& rel_time);
Effects: Equivalent to:
return run_one_until(chrono::steady_clock::now() + rel_time);
template<class Clock, class Duration> count_type run_one_until(const chrono::time_point<Clock, Duration>& abs_time);
Effects: If the
io_contextobject has no outstanding work, performsstop(). Otherwise, blocks while the io_context has outstanding work, or until the expiration of the absolute timeout (C++Std [thread.req.timing]) specified byabs_time, or until theio_contextis stopped, or until one function object has been executed.
If an executed function object throws an exception, the exception propagates to the caller of
run_one(). Theio_contextstate is as if the function object had returned normally.
Returns:
1if a function object was executed, otherwise0.
Notes: This function may invoke additional function objects through nested calls to the
io_contextexecutor'sdispatchmember function. These do not count towards the return value.
count_type poll();
Effects: Equivalent to:
count_type n = 0; while (poll_one()) if (n != numeric_limits<count_type>::max()) ++n;
Returns:
n.
count_type poll_one();
Effects: If the
io_contextobject has no outstanding work, performsstop(). Otherwise, if there is a function object ready for immediate execution, executes it.
If an executed function object throws an exception, the exception propagates to the caller of
poll_one(). Theio_contextstate is as if the function object had returned normally.
Returns:
1if a function object was invoked, otherwise0.
Notes: This function may invoke additional function objects through nested calls to the
io_contextexecutor'sdispatchmember function. These do not count towards the return value.
void stop();
Effects: Stops the
io_context. Concurrent calls to any run function will end as soon as possible. If a call to a run function is currently executing a function object, the call will end only after completion of that function object. The call tostop()returns without waiting for concurrent calls to run functions to complete.
Postconditions:
stopped() == true.
[Note: When
stopped() == true, subsequent calls to a run function will exit immediately with a return value of0, without executing any function objects. Anio_contextremains in the stopped state until a call torestart(). —end note]
bool stopped() const noexcept;
Returns:
trueif theio_contextis stopped.
void restart();
Postconditions:
stopped() == false.
namespace std { namespace experimental { namespace net { inline namespace v1 { class io_context::executor_type { public: // construct / copy / destroy: executor_type(const executor_type& other) noexcept; executor_type(executor_type&& other) noexcept; executor_type& operator=(const executor_type& other) noexcept; executor_type& operator=(executor_type&& other) noexcept; // executor operations: bool running_in_this_thread() const noexcept; io_context& context() noexcept; void on_work_started() noexcept; void on_work_finished() noexcept; template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a); template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a); }; bool operator==(const io_context::executor_type& a, const io_context::executor_type& b) noexcept; bool operator!=(const io_context::executor_type& a, const io_context::executor_type& b) noexcept; template<> struct is_executor<io_context::executor_type> : true_type {}; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          io_context::executor_type is a type satisfying Executor requirements. Objects of
          type io_context::executor_type are associated with an
          io_context, and function
          objects submitted using the dispatch,
          post, or defer member functions will be executed
          by the io_context from
          within a run function.]
        
executor_type(const executor_type& other) noexcept;
Postconditions:
*this == other.
executor_type(executor_type&& other) noexcept;
Postconditions:
*thisis equal to the prior value ofother.
executor_type& operator=(const executor_type& other) noexcept;
Postconditions:
*this == other.
Returns:
*this.
executor_type& operator=(executor_type&& other) noexcept;
Postconditions:
*thisis equal to the prior value ofother.
Returns:
*this.
bool running_in_this_thread() const noexcept;
Returns:
trueif the current thread of execution is calling a run function of the associatedio_contextobject. [Note: That is, the current thread of execution's call chain includes a run function. —end note]
io_context& context() noexcept;
Returns: A reference to the associated
io_contextobject.
void on_work_started() noexcept;
Effects: Increment the count of outstanding work associated with the
io_context.
void on_work_finished() noexcept;
Effects: Decrement the count of outstanding work associated with the
io_context.
template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a);
Effects: If
running_in_this_thread()istrue, callsDECAY_COPY(forward<Func>(f))()(C++Std [thread.decaycopy]). [Note: Iffexits via an exception, the exception propagates to the caller ofdispatch(). —end note] Otherwise, callspost(forward<Func>(f), a).
template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a);
Effects: Adds
fto theio_context.
template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a);
Effects: Adds
fto theio_context.
bool operator==(const io_context::executor_type& a, const io_context::executor_type& b) noexcept;
Returns:
addressof(a.context()) == addressof(b.context()).
bool operator!=(const io_context::executor_type& a, const io_context::executor_type& b) noexcept;
Returns:
!(a == b).
[timer] This clause defines components for performing timer operations.
[Example: Performing a synchronous wait operation on a timer:
io_context c; steady_timer t(c); t.expires_after(seconds(5)); t.wait();
—end example]
[Example: Performing an asynchronous wait operation on a timer:
void handler(error_code ec) { ... } ... io_context c; steady_timer t(c); t.expires_after(seconds(5)); t.async_wait(handler); i.run();
—end example]
#include <chrono> namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Clock> struct wait_traits; template<class Clock, class WaitTraits = wait_traits<Clock>> class basic_waitable_timer; typedef basic_waitable_timer<chrono::system_clock> system_timer; typedef basic_waitable_timer<chrono::steady_clock> steady_timer; typedef basic_waitable_timer<chrono::high_resolution_clock> high_resolution_timer; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
            The basic_waitable_timer
            template uses wait traits to allow programs to customize wait and async_wait
            behavior. [Note: Possible uses of wait traits include:
            — To enable timers based on non-realtime clocks.
 — Determining how
            quickly wallclock-based timers respond to system time changes.
            — Correcting for errors or rounding timeouts to boundaries.
 — Preventing
            duration overflow. That is, a program may set a timer's expiry e to be Clock::max() (meaning never reached) or Clock::min()
            (meaning always in the past). As a result, computing the duration until
            timer expiry as e -
            Clock::now()
            may cause overflow. —end note]
          
            For a type Clock meeting
            the Clock requirements
            (C++Std [time.clock.req]), a type X
            meets the WaitTraits
            requirements if it satisfies the requirements listed below.
          
            In the table below, t
            denotes a (possibly const) value of type Clock::time_point;
            and d denotes a (possibly
            const) value of type Clock::duration.
          
Table 10. WaitTraits requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | 
                      Returns a  | 
| 
                       | 
                       | 
                      Returns a  | 
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Clock> struct wait_traits { static typename Clock::duration to_wait_duration( const typename Clock::duration& d); static typename Clock::duration to_wait_duration( const typename Clock::time_point& t); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Class template wait_traits
          satisfies the WaitTraits
          type requirements. Template argument Clock
          is a type meeting the Clock
          requirements (C++Std [time.clock.req]).
        
static typename Clock::duration to_wait_duration( const typename Clock::duration& d);
Returns:
d.
static typename Clock::duration to_wait_duration( const typename Clock::time_point& t);
Returns: Let
nowbeClock::now(). Ifnow + Clock::duration::max()is beforet,Clock::duration::max(); ifnow + Clock::duration::min()is aftert,Clock::duration::min(); otherwise,t - now.
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Clock, class WaitTraits = wait_traits<Clock>> class basic_waitable_timer { public: // types: typedef io_context::executor_type executor_type; typedef Clock clock_type; typedef typename clock_type::duration duration; typedef typename clock_type::time_point time_point; typedef WaitTraits traits_type; // construct / copy / destroy: explicit basic_waitable_timer(io_context& ctx); basic_waitable_timer(io_context& ctx, const time_point& t); basic_waitable_timer(io_context& ctx, const duration& d); basic_waitable_timer(const basic_waitable_timer&) = delete; basic_waitable_timer(basic_waitable_timer&& rhs); ~basic_waitable_timer(); basic_waitable_timer& operator=(const basic_waitable_timer&) = delete; basic_waitable_timer& operator=(basic_waitable_timer&& rhs); // basic_waitable_timer operations: executor_type get_executor() noexcept; size_t cancel(); size_t cancel_one(); time_point expiry() const; size_t expires_at(const time_point& t); size_t expires_after(const duration& d); void wait(); void wait(error_code& ec); template<class CompletionToken> DEDUCED async_wait(CompletionToken&& token); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_waitable_timer
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), and MoveAssignable
          (C++Std [moveassignable]).
        
explicit basic_waitable_timer(io_context& ctx);
Effects: Equivalent to
basic_waitable_timer(ctx, time_point()).
basic_waitable_timer(io_context& ctx, const time_point& t);
Postconditions:
—get_executor() == ctx.get_executor().
—expiry() == t.
basic_waitable_timer(io_context& ctx, const duration& d);
Effects: Sets the expiry time as if by calling
expires_after(d).
Postconditions:
get_executor() == ctx.get_executor().
basic_waitable_timer(basic_waitable_timer&& rhs);
Effects: Move constructs an object of class
basic_waitable_timer<Clock, WaitTraits>that refers to the state originally represented byrhs.
Postconditions:
—get_executor()is equal to the prior value ofrhs.get_executor().
—expiry()returns the same value asrhs.expiry()prior to the constructor invocation.
—rhs.expiry() == time_point().
~basic_waitable_timer();
Effects: Destroys the timer, cancelling any asynchronous wait operations associated with the timer as if by calling
cancel().
basic_waitable_timer& operator=(basic_waitable_timer&& rhs);
Effects: Cancels any outstanding asynchronous operations associated with
*thisas if by callingcancel(), then moves into*thisthe state originally represented byrhs.
Postconditions:
—get_executor()is equal to the prior value ofrhs.get_executor().
—expiry()returns the same value asrhs.expiry()prior to the assignment.
—rhs.expiry() == time_point().
Returns:
*this.
executor_type get_executor() noexcept;
Returns: The associated executor.
size_t cancel();
Effects: Causes any outstanding asynchronous wait operations to complete. Completion handlers for canceled operations are passed an error code
ecsuch thatec == errc::operation_canceledyieldstrue.
Returns: The number of operations that were canceled.
size_t cancel_one();
Effects: Causes the outstanding asynchronous wait operation that was initiated first, if any, to complete as soon as possible. The completion handler for the canceled operation is passed an error code
ecsuch thatec == errc::operation_canceledyieldstrue.
Returns:
1if an operation was cancelled, otherwise0.
time_point expiry() const;
Returns: The expiry time associated with the timer, as previously set using
expires_at()orexpires_after().
size_t expires_at(const time_point& t);
Effects: Cancels outstanding asynchronous wait operations, as if by calling
cancel(). Sets the expiry time associated with the timer.
Returns: The number of operations that were canceled.
Postconditions:
expiry() == t.
size_t expires_after(const duration& d);
Returns:
expires_at(clock_type::now() + d).
void wait(); void wait(error_code& ec);
Effects: Establishes the postcondition as if by repeatedly blocking the calling thread (C++Std [defns.block]) for the relative time produced by
WaitTraits::to_wait_duration(expiry()).
Postconditions:
ec || expiry() <= clock_type::now().
template<class CompletionToken> DEDUCED async_wait(CompletionToken&& token);
Completion signature:
void(error_code ec).
Effects: Initiates an asynchronous wait operation to repeatedly wait for the relative time produced by
WaitTraits::to_wait_duration(e), whereeis a value of typetime_pointsuch thate <= expiry(). The completion handler is submitted for execution only when the conditionec || expiry() <= clock_type::now()yieldstrue.
[Note: To implement
async_wait, anio_contextobjectctxmay maintain a priority queue for each specialization ofbasic_waitable_timer<Clock, WaitTraits>for which a timer object was initialized withctx. Only the time pointeof the earliest outstanding expiry need be passed toWaitTraits::to_wait_duration(e). —end note]
namespace std { namespace experimental { namespace net { inline namespace v1 { enum class stream_errc { eof = implementation defined, not_found = implementation defined }; const error_category& stream_category() noexcept; error_code make_error_code(stream_errc e) noexcept; error_condition make_error_condition(stream_errc e) noexcept; class mutable_buffer; class const_buffer; // buffer type traits: template<class T> is_mutable_buffer_sequence; template<class T> is_const_buffer_sequence; template<class T> is_dynamic_buffer; // buffer sequence access: const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b); const const_buffer* buffer_sequence_begin(const const_buffer& b); const mutable_buffer* buffer_sequence_end(const mutable_buffer& b); const const_buffer* buffer_sequence_end(const const_buffer& b); template <class C> auto buffer_sequence_begin(C& c) -> decltype(c.begin()); template <class C> auto buffer_sequence_begin(const C& c) -> decltype(c.begin()); template <class C> auto buffer_sequence_end(C& c) -> decltype(c.end()); template <class C> auto buffer_sequence_end(const C& c) -> decltype(c.end()); // buffer size: template<class ConstBufferSequence> size_t buffer_size(const ConstBufferSequence& buffers) noexcept; // buffer copy: template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source, max_size) noexcept; // buffer arithmetic: mutable_buffer operator+(const mutable_buffer& b, size_t n) noexcept; mutable_buffer operator+(size_t n, const mutable_buffer& b) noexcept; const_buffer operator+(const const_buffer&, size_t n) noexcept; const_buffer operator+(size_t, const const_buffer&) noexcept; // buffer creation: mutable_buffer buffer(void* p, size_t n) noexcept; const_buffer buffer(const void* p, size_t n) noexcept; mutable_buffer buffer(const mutable_buffer& b) noexcept; mutable_buffer buffer(const mutable_buffer& b, size_t n) noexcept; const_buffer buffer(const const_buffer& b) noexcept; const_buffer buffer(const const_buffer& b, size_t n) noexcept; template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept; template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept; template<class T, size_t N> mutable_buffer buffer(array<T, N>& data) noexcept; template<class T, size_t N> const_buffer buffer(array<const T, N>& data) noexcept; template<class T, size_t N> const_buffer buffer(const array<T, N>& data) noexcept; template<class T, class Allocator> mutable_buffer buffer(vector<T, Allocator>& data) noexcept; template<class T, class Allocator> const_buffer buffer(const vector<T, Allocator>& data) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data) noexcept; template<class CharT, class Traits> const_buffer buffer(basic_string_view<CharT, Traits> data) noexcept; template<class T, size_t N> mutable_buffer buffer(T (&data)[N], size_t n) noexcept; template<class T, size_t N> const_buffer buffer(const T (&data)[N], size_t n) noexcept; template<class T, size_t N> mutable_buffer buffer(array<T, N>& data, size_t n) noexcept; template<class T, size_t N> const_buffer buffer(array<const T, N>& data, size_t n) noexcept; template<class T, size_t N> const_buffer buffer(const array<T, N>& data, size_t n) noexcept; template<class T, class Allocator> mutable_buffer buffer(vector<T, Allocator>& data, size_t n) noexcept; template<class T, class Allocator> const_buffer buffer(const vector<T, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits> const_buffer buffer(basic_string_view<CharT, Traits> data, size_t n) noexcept; template<class T, Allocator> class dynamic_vector_buffer; template<class CharT, class Traits, Allocator> class dynamic_string_buffer; // dynamic buffer creation: template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec) noexcept; template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec, size_t n) noexcept; template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept; template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept; class transfer_all; class transfer_at_least; class transfer_exactly; // synchronous read operations: template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers); template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, error_code& ec); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec); template<class SyncReadStream, class DynamicBuffer> size_t read(SyncReadStream& stream, DynamicBuffer&& b); template<class SyncReadStream, class DynamicBuffer> size_t read(SyncReadStream& stream, DynamicBuffer&& b, error_code& ec); template<class SyncReadStream, class DynamicBuffer, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition); template<class SyncReadStream, class DynamicBuffer, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, error_code& ec); // asynchronous read operations: template<class AsyncReadStream, class MutableBufferSequence, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionToken&& token); template<class AsyncReadStream, class MutableBufferSequence, class CompletionCondition, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, DynamicBuffer&& b, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionCondition, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, CompletionToken&& token); // synchronous write operations: template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers); template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, error_code& ec); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec); template<class SyncWriteStream, class DynamicBuffer> size_t write(SyncWriteStream& stream, DynamicBuffer&& b); template<class SyncWriteStream, class DynamicBuffer> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, error_code& ec); template<class SyncWriteStream, class DynamicBuffer, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition); template<class SyncWriteStream, class DynamicBuffer, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, error_code& ec); // asynchronous write operations: template<class AsyncWriteStream, class ConstBufferSequence, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionToken&& token); template<class AsyncWriteStream, class ConstBufferSequence, class CompletionCondition, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBuffer, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, DynamicBuffer&& b, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBuffer, class CompletionCondition, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, CompletionToken&& token); // synchronous delimited read operations: template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim, error_code& ec); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim, error_code& ec); // asynchronous delimited read operations: template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read_until(AsyncReadStream& s, DynamicBuffer&& b, char delim, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read_until(AsyncReadStream& s, DynamicBuffer&& b, string_view delim, CompletionToken&& token); } // inline namespace v1 } // namespace net } // namespace experimental template<> struct is_error_code_enum< experimental::net::v1::stream_errc> : public true_type {}; } // namespace std
[buffer.reqmts.mutablebuffersequence]
            A mutable buffer sequence represents a set of memory
            regions that may be used to receive the output of an operation, such
            as the receive operation
            of a socket.
          
            A type X meets the MutableBufferSequence requirements
            if it satisfies the requirements of Destructible
            (C++Std [destructible]) and CopyConstructible
            (C++Std [copyconstructible]), as well as the additional requirements
            listed below.
          
            In the table below, x
            denotes a (possibly const) value of type X,
            and u denotes an identifier.
          
Table 11. MutableBufferSequence requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      An iterator type meeting the requirements for bidirectional
                      iterators (C++Std [bidirectional.iterators]) whose value type
                      is convertible to  | |
| 
 X u(x); 
 | 
                      post: equal( std::experimental::net::buffer_sequence_begin(x), std::experimental::net::buffer_sequence_end(x), std::experimental::net::buffer_sequence_begin(u), std::experimental::net::buffer_sequence_end(u), [](const typename X::value_type& v1, const typename X::value_type& v2) { mutable_buffer b1(v1); mutable_buffer b2(v2); return b1.data() == b2.data() && b1.size() == b2.size(); }) 
 | 
[buffer.reqmts.constbuffersequence]
            A constant buffer sequence represents a set of memory
            regions that may be used as input to an operation, such as the send operation of a socket.
          
            A type X meets the ConstBufferSequence requirements if
            it satisfies the requirements of Destructible
            (C++Std [destructible]) and CopyConstructible
            (C++Std [copyconstructible]), as well as the additional requirements
            listed below.
          
            In the table below, x
            denotes a (possibly const) value of type X,
            and u denotes an identifier.
          
Table 12. ConstBufferSequence requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      An iterator type meeting the requirements for bidirectional
                      iterators (C++Std [bidirectional.iterators]) whose value type
                      is convertible to  | |
| 
 X u(x); 
 | 
                      post: equal( std::experimental::net::buffer_sequence_begin(x), std::experimental::net::buffer_sequence_end(x), std::experimental::net::buffer_sequence_begin(u), std::experimental::net::buffer_sequence_end(u), [](const typename X::value_type& v1, const typename X::value_type& v2) { const_buffer b1(v1); const_buffer b2(v2); return b1.data() == b2.data() && b1.size() == b2.size(); }) 
 | 
            A dynamic buffer encapsulates memory storage that may be automatically
            resized as required, where the memory is divided into two regions: readable
            bytes followed by writable bytes. These memory regions are internal to
            the dynamic buffer, but direct access to the elements is provided to
            permit them to be efficiently used with I/O operations. [Note:
            Such as the send or
            receive operations of
            a socket. The readable bytes would be used as the constant buffer sequence
            for send, and the writable
            bytes used as the mutable buffer sequence for receive.
            —end note] Data written to the writable bytes of
            a dynamic buffer object is appended to the readable bytes of the same
            object.
          
            A type X meets the DynamicBuffer requirements if it satisfies
            the requirements of Destructible
            (C++Std [destructible]) and MoveConstructible
            (C++Std [moveconstructible]), as well as the additional requirements
            listed below.
          
            In the table below, x
            denotes a value of type X,
            x1 denotes a (possibly
            const) value of type X,
            and n denotes a (possibly
            const) value of type size_t.
          
Table 13. DynamicBuffer requirements
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | type meeting ConstBufferSequence requirements. | This type represents the memory associated with the readable bytes. | 
| 
                       | type meeting MutableBufferSequence requirements. | This type represents the memory associated with the writable bytes. | 
| 
                       | 
                       | Returns the number of readable bytes. | 
| 
                       | 
                       | 
                      Returns the maximum number of bytes, both readable and writable,
                      that can be held by  | 
| 
                       | 
                       | 
                      Returns the maximum number of bytes, both readable and writeable,
                      that can be held by  | 
| 
                       | 
                       | 
                      Returns a constant buffer sequence  | 
| 
                       | 
                       | 
                      Returns a mutable buffer sequence  | 
| 
                       | 
                      Appends  | |
| 
                       | 
                      Removes  | 
            A read operation is an operation that reads data
            into a mutable buffer sequence argument of a type meeting MutableBufferSequence requirements.
            The mutable buffer sequence specifies memory where the data should be
            placed. A read operation shall always fill a buffer in the sequence completely
            before proceeding to the next.
          
            A write operation is an operation that writes data
            from a constant buffer sequence argument of a type meeting ConstBufferSequence requirements.
            The constant buffer sequence specifies memory where the data to be written
            is located. A write operation shall always write a buffer in the sequence
            completely before proceeding to the next.
          
If a read or write operation is also an asynchronous operation, the operation shall maintain one or more copies of the buffer sequence until such time as the operation no longer requires access to the memory specified by the buffers in the sequence. The program shall ensure the memory remains valid until:
— the last copy of the buffer sequence is destroyed, or
— the completion handler for the asynchronous operation is invoked,
whichever comes first.
namespace std { namespace experimental { namespace net { inline namespace v1 { class mutable_buffer { public: // constructors: mutable_buffer() noexcept; mutable_buffer(void* p, size_t n) noexcept; // members: void* data() const noexcept; size_t size() const noexcept; private: void* data_; // exposition only size_t size_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The mutable_buffer class
          satisfies requirements of MutableBufferSequence, DefaultConstructible (C++Std [defaultconstructible]),
          and CopyAssignable (C++Std
          [copyassignable]).
        
mutable_buffer() noexcept;
Postconditions:
data_ == nullptrandsize_ == 0.
mutable_buffer(void* p, size_t n) noexcept;
Postconditions:
data_ == pandsize_ == n.
void* data() const noexcept;
Returns:
data_.
size_t size() const noexcept;
Returns:
size_.
namespace std { namespace experimental { namespace net { inline namespace v1 { class const_buffer { public: // constructors: const_buffer() noexcept; const_buffer(const void* p, size_t n) noexcept; const_buffer(const mutable_buffer& b) noexcept; // members: const void* data() const noexcept; size_t size() const noexcept; private: const void* data_; // exposition only size_t size_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The const_buffer class
          satisfies requirements of ConstBufferSequence, DefaultConstructible (C++Std [defaultconstructible]),
          and CopyAssignable (C++Std
          [copyassignable]).
        
const_buffer() noexcept;
Postconditions:
data_ == nullptrandsize_ == 0.
const_buffer(const void* p, size_t n) noexcept;
Postconditions:
data_ == pandsize_ == n.
const_buffer(const mutable_buffer& b);
Postconditions:
data_ == b.data_andsize_ == b.size_.
const void* data() const noexcept;
Returns:
data_.
size_t size() const noexcept;
Returns:
size_.
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T> is_mutable_buffer_sequence; template<class T> is_const_buffer_sequence; template<class T> is_dynamic_buffer; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          This sub-clause contains templates that may be used to query the properties
          of a type at compile time. Each of these templates is a UnaryTypeTrait
          (C++Std [meta.rqmts]) with a BaseCharacteristic of true_type
          if the corresponding condition is true, otherwise false_type.
        
Table 14. Buffer type traits
| Template | Condition | Preconditions | 
|---|---|---|
| 
                     | 
                     | 
                     | 
| 
                     | 
                     | 
                     | 
| 
                     | 
                     | 
                     | 
const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b); const const_buffer* buffer_sequence_begin(const const_buffer& b);
Returns:
std::addressof(b).
const mutable_buffer* buffer_sequence_end(const mutable_buffer& b); const const_buffer* buffer_sequence_end(const const_buffer& b);
Returns:
std::addressof(b) + 1.
template <class C> auto buffer_sequence_begin(C& c) -> decltype(c.begin()); template <class C> auto buffer_sequence_begin(const C& c) -> decltype(c.begin());
Returns:
c.begin().
template <class C> auto buffer_sequence_end(C& c) -> decltype(c.end()); template <class C> auto buffer_sequence_end(const C& c) -> decltype(c.end());
Returns:
c.end().
template<class ConstBufferSequence> size_t buffer_size(const ConstBufferSequence& buffers) noexcept;
Returns: The total size of all buffers in the sequence, as if computed as follows:
size_t total_size = 0; auto i = std::experimental::net::buffer_sequence_begin(buffers); auto end = std::experimental::net::buffer_sequence_end(buffers); for (; i != end; ++i) { const_buffer b(v); total_size += b.size(); } return total_size;
template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source) noexcept; template<class MutableBufferSequence, class ConstBufferSequence> size_t buffer_copy(const MutableBufferSequence& dest, const ConstBufferSequence& source, size_t max_size) noexcept;
Effects: Copies bytes from the buffer sequence
sourceto the buffer sequencedest, as if by calls tomemcpy.
The number of bytes copied is the lesser of:
—buffer_size(dest);
—buffer_size(source); and
—max_size, if specified.
The mutable buffer sequence
destspecifies memory where the data should be placed. The operation always fills a buffer in the sequence completely before proceeding to the next.
The constant buffer sequence
sourcespecifies memory where the data to be written is located. The operation always copies a buffer in the sequence completely before proceeding to the next.
Returns: The number of bytes copied from
sourcetodest.
mutable_buffer operator+(const mutable_buffer& b, size_t n) noexcept; mutable_buffer operator+(size_t n, const mutable_buffer& b) noexcept;
Returns: A
mutable_bufferequivalent tomutable_buffer( static_cast<char*>(b.data()) + min(n, b.size()), b.size() - min(n, b.size()));
const_buffer operator+(const const_buffer& b, size_t n) noexcept; const_buffer operator+(size_t n, const const_buffer& b) noexcept;
Returns: A
const_bufferequivalent toconst_buffer( static_cast<const char*>(b.data()) + min(n, b.size()), b.size() - min(n, b.size()));
          In the functions below, T
          must be a trivially copyable or standard-layout type (C++Std [basic.types]).
        
          For the function overloads below that accept an argument of type vector<>,
          the buffer objects returned are invalidated by any vector operation that
          also invalidates all references, pointers and iterators referring to the
          elements in the sequence (C++Std [vector]).
        
          For the function overloads below that accept an argument of type basic_string<>,
          the buffer objects returned are invalidated according to the rules defined
          for invalidation of references, pointers and iterators referring to elements
          of the sequence (C++Std [string.require]).
        
mutable_buffer buffer(void* p, size_t n) noexcept;
Returns:
mutable_buffer(p, n).
const_buffer buffer(const void* p, size_t n) noexcept;
Returns:
const_buffer(p, n).
mutable_buffer buffer(const mutable_buffer& b) noexcept;
Returns:
b.
mutable_buffer buffer(const mutable_buffer& b, size_t n) noexcept;
Returns:
mutable_buffer(b.data(), min(b.size(), n)).
const_buffer buffer(const const_buffer& b) noexcept;
Returns:
b.
const_buffer buffer(const const_buffer& b, size_t n) noexcept;
Returns:
const_buffer(b.data(), min(b.size(), n)).
template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept; template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept; template<class T, size_t N> mutable_buffer buffer(array<T, N>& data) noexcept; template<class T, size_t N> const_buffer buffer(array<const T, N>& data) noexcept; template<class T, size_t N> const_buffer buffer(const array<T, N>& data) noexcept; template<class T, class Allocator> mutable_buffer buffer(vector<T, Allocator>& data) noexcept; template<class T, class Allocator> const_buffer buffer(const vector<T, Allocator>& data) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data) noexcept; template<class CharT, class Traits> const_buffer buffer(basic_string_view<CharT, Traits> data) noexcept;
Returns:
buffer( begin(data) != end(data) ? std::addressof(*begin(data)) : nullptr, (end(data) - begin(data)) * sizeof(*begin(data)));
template<class T, size_t N> mutable_buffer buffer(T (&data)[N], size_t n) noexcept; template<class T, size_t N> const_buffer buffer(const T (&data)[N], size_t n) noexcept; template<class T, size_t N> mutable_buffer buffer(array<T, N>& data, size_t n) noexcept; template<class T, size_t N> const_buffer buffer(array<const T, N>& data, size_t n) noexcept; template<class T, size_t N> const_buffer buffer(const array<T, N>& data, size_t n) noexcept; template<class T, class Allocator> mutable_buffer buffer(vector<T, Allocator>& data, size_t n) noexcept; template<class T, class Allocator> const_buffer buffer(const vector<T, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits, class Allocator> mutable_buffer buffer(basic_string<CharT, Traits, Allocator>& data, size_t n) noexcept; template<class CharT, class Traits> const_buffer buffer(basic_string_view<CharT, Traits> data, size_t n) noexcept;
Returns:
buffer(buffer(data), n).
          Class template dynamic_vector_buffer
          is an adaptor used to automatically grow or shrink a vector
          object, to reflect the data successfully transferred in an I/O operation.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class T, class Allocator> class dynamic_vector_buffer { public: // types: typedef const_buffer const_buffers_type; typedef mutable_buffer mutable_buffers_type; // constructors: explicit dynamic_vector_buffer(vector<T, Allocator>& vec) noexcept; dynamic_vector_buffer(vector<T, Allocator>& vec, size_t maximum_size) noexcept; dynamic_vector_buffer(dynamic_vector_buffer&&) = default; // members: size_t size() const noexcept; size_t max_size() const noexcept; size_t capacity() const noexcept; const_buffers_type data() const noexcept; mutable_buffers_type prepare(size_t n); void commit(size_t n); void consume(size_t n); private: vector<T, Allocator>& vec_; // exposition only size_t size_; // exposition only const size_t max_size_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The dynamic_vector_buffer
          class template meets the requirements of DynamicBuffer.
        
          The dynamic_vector_buffer
          class template requires that T
          is a trivially copyable or standard-layout type (C++Std [basic.types])
          and that sizeof(T) ==
          1.
        
explicit dynamic_vector_buffer(vector<T, Allocator>& vec) noexcept;
Effects: Initializes
vec_withvec,size_withvec.size(), andmax_size_withvec.max_size().
dynamic_vector_buffer(vector<T, Allocator>& vec, size_t maximum_size) noexcept;
Requires:
vec.size() <= maximum_size.
Effects: Initializes
vec_withvec,size_withvec.size(), andmax_size_withmaximum_size.
size_t size() const noexcept;
Returns:
size_.
size_t max_size() const noexcept;
Returns:
max_size_.
size_t capacity() const noexcept;
Returns:
vec_.capacity().
const_buffers_type data() const noexcept;
Returns:
buffer(vec_, size_).
mutable_buffers_type prepare(size_t n);
Effects: Performs
vec_.resize(size_ + n).
Returns:
buffer(buffer(vec_) + size_, n).
Throws:
length_errorifsize() + nexceedsmax_size().
void commit(size_t n);
Effects: Performs:
size_ += min(n, vec_.size() - size_); vec_.resize(size_);
void consume(size_t n);
Effects: Performs:
size_t m = min(n, size_); vec_.erase(vec_.begin(), vec_.begin() + m); size_ -= m;
          Class template dynamic_string_buffer
          is an adaptor used to automatically grow or shrink a basic_string
          object, to reflect the data successfully transferred in an I/O operation.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class CharT, class Traits, class Allocator> class dynamic_string_buffer { public: // types: typedef const_buffer const_buffers_type; typedef mutable_buffer mutable_buffers_type; // constructors: explicit dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept; dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str, size_t maximum_size) noexcept; dynamic_string_buffer(dynamic_string_buffer&&) = default; // members: size_t size() const noexcept; size_t max_size() const noexcept; size_t capacity() const noexcept; const_buffers_type data() const noexcept; mutable_buffers_type prepare(size_t n); void commit(size_t n) noexcept; void consume(size_t n); private: basic_string<CharT, Traits, Allocator>& str_; // exposition only size_t size_; // exposition only const size_t max_size_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The dynamic_string_buffer
          class template meets the requirements of DynamicBuffer.
        
          The dynamic_string_buffer
          class template requires that sizeof(CharT) == 1.
        
explicit dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
Effects: Initializes
str_withstr,size_withstr.size(), andmax_size_withstr.max_size().
dynamic_string_buffer(basic_string<CharT, Traits, Allocator>& str, size_t maximum_size) noexcept;
Requires:
str.size() <= maximum_size.
Effects: Initializes
str_withstr,size_withstr.size(), andmax_size_withmaximum_size.
size_t size() const noexcept;
Returns:
size_.
size_t max_size() const noexcept;
Returns:
max_size_.
size_t capacity() const noexcept;
Returns:
str_.capacity().
const_buffers_type data() const noexcept;
Returns:
buffer(str_, size_).
mutable_buffers_type prepare(size_t n);
Effects: Performs
str_.resize(size_ + n).
Returns:
buffer(buffer(str_) + size_, n).
Throws:
length_errorifsize() + nexceedsmax_size().
void commit(size_t n) noexcept;
Effects: Performs:
size_ += min(n, str_.size() - size_); str_.resize(size_);
void consume(size_t n);
Effects: Performs:
size_t m = min(n, size_); str_.erase(m); size_ -= m;
template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec) noexcept;
Returns:
dynamic_vector_buffer<T, Allocator>(vec).
template<class T, class Allocator> dynamic_vector_buffer<T, Allocator> dynamic_buffer(vector<T, Allocator>& vec, size_t n) noexcept;
Returns:
dynamic_vector_buffer<T, Allocator>(vec, n).
template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str) noexcept;
Returns:
dynamic_string_buffer<CharT, Traits, Allocator>(str).
template<class CharT, class Traits, class Allocator> dynamic_string_buffer<CharT, Traits, Allocator> dynamic_buffer(basic_string<CharT, Traits, Allocator>& str, size_t n) noexcept;
Returns:
dynamic_string_buffer<CharT, Traits, Allocator>(str, n).
[buffer.stream.reqmts.syncreadstream]
            A type X meets the SyncReadStream requirements if it satisfies
            the requirements listed below.
          
            In the table below, a
            denotes a value of type X,
            mb denotes a (possibly
            const) value satisfying the MutableBufferSequence requirements,
            and ec denotes an object
            of type error_code.
          
Table 15. SyncReadStream requirements
| operation | type | semantics, pre/post-conditions | 
|---|---|---|
| 
                       | 
                       | 
                      Meets the requirements for a read
                      operation. | 
[buffer.stream.reqmts.asyncreadstream]
            A type X meets the AsyncReadStream requirements if it
            satisfies the requirements listed below.
          
            In the table below, a
            denotes a value of type X,
            mb denotes a (possibly
            const) value satisfying the MutableBufferSequence requirements,
            and t is a completion
            token.
          
Table 16. AsyncReadStream requirements
| operation | type | semantics, pre/post-conditions | 
|---|---|---|
| 
                       | A type satisfying the Executor requirements. | Returns the associated I/O executor. | 
| 
                       | The return type is determined according to the requirements for an asynchronous operation. | 
                      Meets the requirements for a read
                      operation and an asynchronous
                      operation with completion signature  | 
[buffer.stream.reqmts.syncwritestream]
            A type X meets the SyncWriteStream requirements if it
            satisfies the requirements listed below.
          
            In the table below, a
            denotes a value of type X,
            cb denotes a (possibly
            const) value satisfying the ConstBufferSequence requirements,
            and ec denotes an object
            of type error_code.
          
Table 17. SyncWriteStream requirements
| operation | type | semantics, pre/post-conditions | 
|---|---|---|
| 
                       | 
                       | 
                      Meets the requirements for a write
                      operation. | 
[buffer.stream.reqmts.asyncwritestream]
            A type X meets the AsyncWriteStream requirements if it
            satisfies the requirements listed below.
          
            In the table below, a
            denotes a value of type X,
            cb denotes a (possibly
            const) value satisfying the ConstBufferSequence requirements,
            and t is a completion
            token.
          
Table 18. AsyncWriteStream requirements
| operation | type | semantics, pre/post-conditions | 
|---|---|---|
| 
                       | A type satisfying the Executor requirements. | Returns the associated I/O executor. | 
| 
                       | The return type is determined according to the requirements for an asynchronous operation. | 
                      Meets the requirements for a write
                      operation and an asynchronous
                      operation with completion signature  | 
[buffer.stream.reqmts.completioncondition]
            A completion condition is a function object that
            is used with the algorithms read, async_read, write, and async_write to determine when
            the algorithm has completed transferring data.
          
            A type X meets the CompletionCondition requirements if
            it satisfies the requirements of Destructible
            (C++Std [destructible]) and CopyConstructible
            (C++Std [copyconstructible]), as well as the additional requirements
            listed below.
          
            In the table below, x
            denotes a value of type X,
            ec denotes a (possibly
            const) value of type error_code,
            and n denotes a (possibly
            const) value of type size_t.
          
Table 19. CompletionCondition requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | 
                      Let  | 
          The class transfer_all
          is a completion condition that is used to specify that a read or write
          operation should continue until all of the data has been transferred, or
          until an error occurs.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class transfer_all { public: size_t operator()(const error_code& ec, size_t) const; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The class transfer_all
          satisfies the CompletionCondition requirements.
        
size_t operator()(const error_code& ec, size_t) const;
Returns: If
!ec, an unspecified non-zero value. Otherwise0.
[buffer.stream.transfer.at.least]
          The class transfer_at_least
          is a completion condition that is used to specify that a read or write
          operation should continue until a minimum number of bytes has been transferred,
          or until an error occurs.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class transfer_at_least { public: explicit transfer_at_least(size_t m); size_t operator()(const error_code& ec, size_t s) const; private: size_t minimum_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The class transfer_at_least
          satisfies the CompletionCondition requirements.
        
explicit transfer_at_least(size_t m);
Postconditions:
minimum_ == m.
size_t operator()(const error_code& ec, size_t n) const;
Returns: If
!ec && n < minimum_, an unspecified non-zero value. Otherwise0.
[buffer.stream.transfer.exactly]
          The class transfer_exactly
          is a completion condition that is used to specify that a read or write
          operation should continue until an exact number of bytes has been transferred,
          or until an error occurs.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { class transfer_exactly { public: explicit transfer_exactly(size_t e); size_t operator()(const error_code& ec, size_t s) const; private: size_t exact_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The class transfer_exactly
          satisfies the CompletionCondition requirements.
        
explicit transfer_exactly(size_t e);
Postconditions:
exact_ == e.
size_t operator()(const error_code& ec, size_t n) const;
Returns: If
!ec && n < exact_, the result ofmin(exact_ - n, N), whereNis an unspecified non-zero value. Otherwise0.
template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers); template<class SyncReadStream, class MutableBufferSequence> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, error_code& ec); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncReadStream, class MutableBufferSequence, class CompletionCondition> size_t read(SyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec);
Effects: Clears
ec, then reads data from the buffer-oriented synchronous read stream objectstreamby performing zero or more calls to the stream'sread_somemember function.
The
completion_conditionparameter specifies a completion condition to be called prior to each call to the stream'sread_somemember function. The completion condition is passed theerror_codevalue from the most recentread_somecall, and the total number of bytes transferred in the synchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequentread_somecall. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The synchronous read operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers); or
— the completion condition returns
0.
On return,
eccontains theerror_codevalue from the most recentread_somecall.
Returns: The total number of bytes transferred in the synchronous read operation.
Remarks: This function shall not participate in overload resolution unless
is_mutable_buffer_sequence<MutableBufferSequence>::valueistrue.
template<class SyncReadStream, class DynamicBuffer> size_t read(SyncReadStream& stream, DynamicBuffer&& b); template<class SyncReadStream, class DynamicBuffer> size_t read(SyncReadStream& stream, DynamicBuffer&& b, error_code& ec); template<class SyncReadStream, class DynamicBuffer, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition); template<class SyncReadStream, class DynamicBuffer, class CompletionCondition> size_t read(SyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, error_code& ec);
Effects: Clears
ec, then reads data from the synchronous read stream objectstreamby performing zero or more calls to the stream'sread_somemember function.
Data is placed into the dynamic buffer object
b. A mutable buffer sequence is obtained prior to eachread_somecall usingb.prepare(N), whereNis an unspecified value less than or equal tob.max_size() - b.size(). [Note: Implementations are encouraged to useb.capacity()when determiningN, to minimize the number ofread_somecalls performed on the stream. —end note] After eachread_somecall, the implementation performsb.commit(n), wherenis the return value fromread_some.
The
completion_conditionparameter specifies a completion condition to be called prior to each call to the stream'sread_somemember function. The completion condition is passed theerror_codevalue from the most recentread_somecall, and the total number of bytes transferred in the synchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequentread_somecall. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The synchronous read operation continues until:
—
b.size() == b.max_size(); or
— the completion condition returns
0.
On return,
eccontains theerror_codevalue from the most recentread_somecall.
Returns: The total number of bytes transferred in the synchronous read operation.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer<DynamicBuffer>::valueistrue.
template<class AsyncReadStream, class MutableBufferSequence, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionToken&& token); template<class AsyncReadStream, class MutableBufferSequence, class CompletionCondition, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Reads data from the buffer-oriented asynchronous read stream object
streamby invoking the stream'sasync_read_somemember function (henceforth referred to as asynchronous read_some operations) zero or more times.
The
completion_conditionparameter specifies a completion condition to be called prior to each asynchronous read_some operation. The completion condition is passed theerror_codevalue from the most recent asynchronous read_some operation, and the total number of bytes transferred in the asynchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequent asynchronous read_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
This asynchronous read operation is outstanding until:
— the total number of bytes transferred is equal to
buffer_size(buffers); or
— the completion condition returns
0.
The program shall ensure the
AsyncReadStreamobjectstreamis valid until the completion handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ecis theerror_codevalue from the most recent asynchronous read_some operation, andnis the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_mutable_buffer_sequence<MutableBufferSequence>::valueistrue.
template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, DynamicBuffer&& b, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionCondition, class CompletionToken> DEDUCED async_read(AsyncReadStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream object
streamby performing one or more asynchronous read_some operations on the stream.
Data is placed into the dynamic buffer object
b. A mutable buffer sequence is obtained prior to eachasync_read_somecall usingb.prepare(N), whereNis an unspecified value such thatNis less than or equal tob.max_size() - b.size(). [Note: Implementations are encouraged to useb.capacity()when determiningN, to minimize the number of asynchronous read_some operations performed on the stream. —end note] After the completion of each asynchronous read_some operation, the implementation performsb.commit(n), wherenis the value passed to the asynchronous read_some operation's completion handler.
The
completion_conditionparameter specifies a completion condition to be called prior to each asynchronous read_some operation. The completion condition is passed theerror_codevalue from the most recent asynchronous read_some operation, and the total number of bytes transferred in the asynchronous read operation so far. The completion condition return value specifies the maximum number of bytes to be read on the subsequent asynchronous read_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The asynchronous read operation is outstanding until:
—
b.size() == b.max_size(); or
— the completion condition returns
0.
The program shall ensure the
AsyncReadStreamobjectstreamis valid until the completion handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ecis theerror_codevalue from the most recent asynchronous read_some operation, andnis the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer<DynamicBuffer>::valueistrue.
template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers); template<class SyncWriteStream, class ConstBufferSequence> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, error_code& ec); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition); template<class SyncWriteStream, class ConstBufferSequence, class CompletionCondition> size_t write(SyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, error_code& ec);
Effects: Writes data to the buffer-oriented synchronous write stream object
streamby performing zero or more calls to the stream'swrite_somemember function.
The
completion_conditionparameter specifies a completion condition to be called prior to each call to the stream'swrite_somemember function. The completion condition is passed theerror_codevalue from the most recentwrite_somecall, and the total number of bytes transferred in the synchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequentwrite_somecall. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The synchronous write operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers); or
— the completion condition returns
0.
On return,
eccontains theerror_codevalue from the most recentwrite_somecall.
Returns: The total number of bytes transferred in the synchronous write operation.
Remarks: This function shall not participate in overload resolution unless
is_const_buffer_sequence<ConstBufferSequence>::valueistrue.
template<class SyncWriteStream, class DynamicBuffer> size_t write(SyncWriteStream& stream, DynamicBuffer&& b); template<class SyncWriteStream, class DynamicBuffer> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, error_code& ec); template<class SyncWriteStream, class DynamicBuffer, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition); template<class SyncWriteStream, class DynamicBuffer, class CompletionCondition> size_t write(SyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, error_code& ec);
Effects: Writes data to the synchronous write stream object
streamby performing zero or more calls to the stream'swrite_somemember function.
Data is written from the dynamic buffer object
b. A constant buffer sequence is obtained usingb.data(). After the data has been written to the stream, the implementation performsb.consume(n), wherenis the number of bytes successfully written.
The
completion_conditionparameter specifies a completion condition to be called after each call to the stream'swrite_somemember function. The completion condition is passed theerror_codevalue from the most recentwrite_somecall, and the total number of bytes transferred in the synchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequentwrite_somecall. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The synchronous write operation continues until:
—
b.size() == 0; or
— the completion condition returns
0.
On return,
eccontains theerror_codevalue from the most recentwrite_somecall.
Returns: The total number of bytes transferred in the synchronous write operation.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer<DynamicBuffer>::valueistrue.
template<class AsyncWriteStream, class ConstBufferSequence, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionToken&& token); template<class AsyncWriteStream, class ConstBufferSequence, class CompletionCondition, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to write data to the buffer-oriented asynchronous write stream object
streamby performing zero or more asynchronous operations on the stream using the stream'sasync_write_somemember function (henceforth referred to as asynchronous write_some operations).
The
completion_conditionparameter specifies a completion condition to be called prior to each asynchronous write_some operation. The completion condition is passed theerror_codevalue from the most recent asynchronous write_some operation, and the total number of bytes transferred in the asynchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequent asynchronous write_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The asynchronous write operation continues until:
— the total number of bytes transferred is equal to
buffer_size(buffers); or
— the completion condition returns
0.
The program must ensure the
AsyncWriteStreamobjectstreamis valid until the completion handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ecis theerror_codevalue from the most recent asynchronous write_some operation, andnis the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_const_buffer_sequence<ConstBufferSequence>::valueistrue.
template<class AsyncWriteStream, class DynamicBuffer, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, DynamicBuffer&& b, CompletionToken&& token); template<class AsyncWriteStream, class DynamicBuffer, class CompletionCondition, class CompletionToken> DEDUCED async_write(AsyncWriteStream& stream, DynamicBuffer&& b, CompletionCondition completion_condition, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to write data to the buffer-oriented asynchronous write stream object
streamby performing zero or more asynchronous write_some operations on the stream.
Data is written from the dynamic buffer object
b. A constant buffer sequence is obtained usingb.data(). After the data has been written to the stream, the implementation performsb.consume(n), wherenis the number of bytes successfully written.
The
completion_conditionparameter specifies a completion condition to be called prior to each asynchronous write_some operation. The completion condition is passed theerror_codevalue from the most recent asynchronous write_some operation, and the total number of bytes transferred in the asynchronous write operation so far. The completion condition return value specifies the maximum number of bytes to be written on the subsequent asynchronous write_some operation. Overloads where a completion condition is not specified behave as if called with an object of classtransfer_all.
The asynchronous write operation continues until:
—
b.size() == 0; or
— the completion condition returns
0.
The program must ensure both the
AsyncWriteStreamobjectstreamand the memory associated with the dynamic bufferbare valid until the completion handler for the asynchronous operation is invoked.
On completion of the asynchronous operation,
ecis theerror_codevalue from the most recent asynchronous write_some operation, andnis the total number of bytes transferred.
Remarks: This function shall not participate in overload resolution unless
is_dynamic_buffer<DynamicBuffer>::valueistrue.
template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, char delim, error_code& ec); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim); template<class SyncReadStream, class DynamicBuffer> size_t read_until(SyncReadStream& s, DynamicBuffer&& b, string_view delim, error_code& ec);
Effects: Reads data from the buffer-oriented synchronous read stream object
streamby performing zero or more calls to the stream'sread_somemember function, until the input sequence of the dynamic buffer objectbcontains the specified delimiterdelim.
Data is placed into the dynamic buffer object
b. A mutable buffer sequence is obtained prior to eachread_somecall usingb.prepare(N), whereNis an unspecified value such thatN <= max_size() - size(). [Note: Implementations are encouraged to useb.capacity()when determiningN, to minimize the number ofread_somecalls performed on the stream. —end note] After eachread_somecall, the implementation performsb.commit(n), wherenis the return value fromread_some.
The synchronous read_until operation continues until:
— the input sequence of
bcontains the delimiterdelim; or
—
b.size() == b.max_size(); or
— an synchronous read_some operation fails.
On exit, if the input sequence of
bcontains the delimiter,ecis set such that!ecistrue. Otherwise, ifb.size() == b.max_size(),ecis set such thatec == stream_errc::not_found. Ifb.size() < b.max_size(),eccontains theerror_codefrom the most recentread_somecall.
Returns: The number of bytes in the input sequence of
bup to and including the delimiter, if present. [Note: On completion, the buffer may contain additional bytes following the delimiter. —end note] Otherwise returns0.
template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read_until(AsyncReadStream& s, DynamicBuffer&& b, char delim, CompletionToken&& token); template<class AsyncReadStream, class DynamicBuffer, class CompletionToken> DEDUCED async_read_until(AsyncReadStream& s, DynamicBuffer&& b, string_view delim, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to read data from the buffer-oriented asynchronous read stream object
streamby performing zero or more asynchronous read_some operations on the stream, until the readable bytes of the dynamic buffer objectbcontain the specified delimiterdelim.
Data is placed into the dynamic buffer object
b. A mutable buffer sequence is obtained prior to eachasync_read_somecall usingb.prepare(N), whereNis an unspecified value such thatN <= max_size() - size(). [Note: Implementations are encouraged to useb.capacity()when determiningN, to minimize the number of asynchronous read_some operations performed on the stream. —end note] After the completion of each asynchronous read_some operation, the implementation performsb.commit(n), wherenis the value passed to the asynchronous read_some operation's completion handler.
The asynchronous read_until operation continues until:
— the readable bytes of
bcontain the delimiterdelim; or
—
b.size() == b.max_size(); or
— an asynchronous read_some operation fails.
The program shall ensure the
AsyncReadStreamobjectstreamis valid until the completion handler for the asynchronous operation is invoked.
If
delimis of typestring_view, the implementation copies the underlying sequence of characters prior to initiating an asynchronous read_some operation on the stream. [Note: This means that the caller is not required to guarantee the validity of the delimiter string after the call toasync_read_untilreturns. —end note]
On completion of the asynchronous operation, if the readable bytes of
bcontain the delimiter,ecis set such that!ecistrue. Otherwise, ifb.size() == b.max_size(),ecis set such thatec == stream_errc::not_found. Ifb.size() < b.max_size(),ecis theerror_codefrom the most recent asynchronous read_some operation.nis the number of readable bytes inbup to and including the delimiter, if present, otherwise0.
namespace std { namespace experimental { namespace net { inline namespace v1 { enum class socket_errc { already_open = implementation defined, not_found = implementation defined }; const error_category& socket_category() noexcept; error_code make_error_code(socket_errc e) noexcept; error_condition make_error_condition(socket_errc e) noexcept; // Sockets: class socket_base; template<class Protocol> class basic_socket; template<class Protocol> class basic_datagram_socket; template<class Protocol> class basic_stream_socket; template<class Protocol> class basic_socket_acceptor; // Socket streams: template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_streambuf; template<class Protocol, class Clock = chrono::steady_clock, class WaitTraits = wait_traits<Clock>> class basic_socket_iostream; // synchronous connect operations: template<class Protocol, class EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints); template<class Protocol, class EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints); error_code& ec); template<class Protocol, class EndpointSequence, class ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, ConnectCondition c); template<class Protocol, class EndpointSequence, class ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, ConnectCondition c, error_code& ec); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, error_code& ec); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, error_code& ec); // asynchronous connect operations: template<class Protocol, class EndpointSequence, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, CompletionToken&& token); template<class Protocol, class EndpointSequence, class ConnectCondition, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, ConnectCondition c, CompletionToken&& token); template<class Protocol, class InputIterator, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, CompletionToken&& token); template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, CompletionToken&& token); } // inline namespace v1 } // namespace net } // namespace experimental template<> struct is_error_code_enum< experimental::net::v1::socket_errc> : public true_type {}; } // namespace std
The figure below illustrates relationships between various types described in this Technical Specification. A solid line from A to B that is terminated by an open arrow indicates that A is derived from B. A solid line from A to B that starts with a diamond and is terminated by a solid arrow indicates that A contains an object of type B. A dotted line from A to B indicates that A is a typedef for the class template B with the specified template argument.
          
        
            In this section, synchronous socket operations are
            those member functions specified as two overloads, with and without an
            argument of type error_code&:
          
R f(A1 a1, A2 a2, ..., AN aN); R f(A1 a1, A2 a2, ..., AN aN, error_code& ec);
            For an object s, the
            conditions under which its synchronous socket operations may block the
            calling thread (C++Std [defns.block]) are determined as follows.
          
If:
            — s.non_blocking()
            == true,
          
            — the synchronous socket operation is specified in terms of a POSIX function
            other than poll,
          
            — that POSIX function lists EWOULDBLOCK
            or EAGAIN in its failure
            conditions, and
          
— the effects of the operation cannot be established immediately
then the synchronous socket operation shall not block the calling thread. [Note: And the effects of the operation are not established. —end note]
Otherwise, the synchronous socket operation shall block the calling thread until the effects are established.
            In this section, asynchronous socket operations
            are those member functions having prefix async_.
          
            For an object s, a program
            may initiate asynchronous socket operations such that there are multiple
            simultaneously outstanding asynchronous operations.
          
            When there are multiple outstanding asynchronous read
            operations on s:
          
            — having no argument flags
            of type socket_base::message_flags, or
          
            — having an argument flags
            of type socket_base::message_flags but where (flags & socket_base::message_out_of_band) == 0
          
            then the buffers are
            filled in the order in which these operations were issued. The order
            of invocation of the completion handlers for these operations is unspecified.
          
            When there are multiple outstanding asynchronous read
            operations on s
            having an argument flags
            of type socket_base::message_flags where (flags &
            socket_base::message_out_of_band)
            != 0
            then the buffers are
            filled in the order in which these operations were issued.
          
            When there are multiple outstanding asynchronous write
            operations on s,
            the buffers are transmitted
            in the order in which these operations were issued. The order of invocation
            of the completion handlers for these operations is unspecified.
          
            Several classes described in this Technical Specification have a member
            type native_handle_type,
            a member function native_handle,
            and member functions that accept arguments of type native_handle_type.
            The presence of these members and their semantics is implementation-defined.
          
            [Note: These members allow implementations to provide
            access to their implementation details. Their names are specified to
            facilitate portable compile-time detection. Actual use of these members
            is inherently non-portable. For operating systems that are based on POSIX,
            implementations are encouraged to define the native_handle_type
            for sockets as int, representing
            the native file descriptor associated with the socket. —end
            note]
          
            A type X meets the Endpoint requirements if it satisfies
            the requirements of Destructible
            (C++Std [destructible]), DefaultConstructible
            (C++Std [defaultconstructible]), CopyConstructible
            (C++Std [copyconstructible]), and CopyAssignable
            (C++Std [copyassignable]), as well as the additional requirements listed
            below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            and u denotes an identifier.
          
Table 20. Endpoint requirements
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      type meeting  | |
| 
                       | 
                       | 
            In the table below, a
            denotes a (possibly const) value of type X,
            b denotes a value of
            type X, and s denotes a (possibly const) value
            of a type that is convertible to size_t
            and denotes a size in bytes.
          
Table 21. Endpoint requirements for extensible implementations
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | 
                      Returns a pointer suitable for passing as the address
                      argument to functions such as POSIX connect,
                      or as the dest_addr argument to functions
                      such as POSIX sendto.
                      The implementation shall perform a  | 
| 
                       | 
                       | 
                      Returns a pointer suitable for passing as the address
                      argument to functions such as POSIX accept,
                      getpeername,
                      getsockname
                      and recvfrom.
                      The implementation shall perform a  | 
| 
                       | 
                       | Returns a value suitable for passing as the address_len argument to functions such as POSIX connect, or as the dest_len argument to functions such as POSIX sendto, after appropriate integer conversion has been performed. | 
| 
                       | 
                      pre:  | |
| 
                       | 
                       | Returns a value suitable for passing as the address_len argument to functions such as POSIX accept, getpeername, getsockname and recvfrom, after appropriate integer conversion has been performed. | 
            A type X meets the Protocol requirements if it satisfies
            the requirements of Destructible
            (C++Std [destructible]), CopyConstructible
            (C++Std [copyconstructible]), and CopyAssignable
            (C++Std [copyassignable]), as well as the additional requirements listed
            below.
          
Table 22. Protocol requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | type meeting endpoint requirements | 
            In the table below, a
            denotes a (possibly const) value of type X.
          
Table 23. Protocol requirements for extensible implementations
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | Returns a value suitable for passing as the domain argument to POSIX socket (or equivalent). | 
| 
                       | 
                       | Returns a value suitable for passing as the type argument to POSIX socket (or equivalent). | 
| 
                       | 
                       | Returns a value suitable for passing as the protocol argument to POSIX socket (or equivalent). | 
[socket.reqmts.acceptableprotocol]
            A type X meets the AcceptableProtocol requirements if
            it satisfies the requirements of Protocol as well as the additional
            requirements listed below.
          
Table 24. AcceptableProtocol requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      A type that satisfies the requirements of  | 
[socket.reqmts.gettablesocketoption]
            A type X meets the GettableSocketOption requirements if
            it satisfies the requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            b denotes a value of
            type X, p denotes a (possibly const) value
            that meets the Protocol
            requirements, and s denotes
            a (possibly const) value of a type that is convertible to size_t and denotes a size in bytes.
          
Table 25. GettableSocketOption requirements for extensible implementations
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | Returns a value suitable for passing as the level argument to POSIX getsockopt (or equivalent). | 
| 
                       | 
                       | Returns a value suitable for passing as the option_name argument to POSIX getsockopt (or equivalent). | 
| 
                       | 
                       | Returns a pointer suitable for passing as the option_value argument to POSIX getsockopt (or equivalent). | 
| 
                       | 
                       | Returns a value suitable for passing as the option_len argument to POSIX getsockopt (or equivalent), after appropriate integer conversion has been performed. | 
| 
                       | 
                      post:  | 
[socket.reqmts.settablesocketoption]
            A type X meets the SettableSocketOption requirements if
            it satisfies the requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            p denotes a (possibly
            const) value that meets the Protocol requirements, and
            u denotes an identifier.
          
Table 26. SettableSocketOption requirements for extensible implementations
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | Returns a value suitable for passing as the level argument to POSIX setsockopt (or equivalent). | 
| 
                       | 
                       | Returns a value suitable for passing as the option_name argument to POSIX setsockopt (or equivalent). | 
| 
                       | 
                       | Returns a pointer suitable for passing as the option_value argument to POSIX setsockopt (or equivalent). | 
| 
                       | 
                       | Returns a value suitable for passing as the option_len argument to POSIX setsockopt (or equivalent), after appropriate integer conversion has been performed. | 
            A type X meets the BooleanSocketOption requirements if
            it satisfies the requirements of Destructible
            (C++Std [destructible]), DefaultConstructible
            (C++Std [defaultconstructible]), CopyConstructible
            (C++Std [copyconstructible]), CopyAssignable
            (C++Std [copyassignable]), GettableSocketOption, and SettableSocketOption,
            X is contextually convertible
            to bool, and X satisfies
            the additional requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            b denotes a (possibly
            const) value of type bool,
            and u denotes an identifier.
          
Table 27. BooleanSocketOption requirements
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      post:  | |
| 
                       | 
                      post:  | |
| 
                       | 
                       | Returns the current boolean value of the socket option object. | 
| 
                       | 
                       | 
                      Returns  | 
| 
                       | 
                       | 
                      Returns  | 
            In this Technical Specification, types that satisfy the BooleanSocketOption requirements are
            defined as follows.
          
class C { public: // constructors: C() noexcept; explicit C(bool v) noexcept; // members: C& operator=(bool v) noexcept; bool value() const noexcept; explicit operator bool() const noexcept; bool operator!() const noexcept; };
Extensible implementations provide the following member functions:
class C { public: template<class Protocol> int level(const Protocol& p) const noexcept; template<class Protocol> int name(const Protocol& p) const noexcept; template<class Protocol> void* data(const Protocol& p) noexcept; template<class Protocol> const void* data(const Protocol& p) const noexcept; template<class Protocol> size_t size(const Protocol& p) const noexcept; template<class Protocol> void resize(const Protocol& p, size_t s); // remainder unchanged private: int value_; // exposition only };
            Let L and N
            identify the POSIX macros to be passed as the level
            and option_name arguments, respectively, to POSIX
            setsockopt
            and getsockopt.
          
C() noexcept;
Postconditions:
!value().
explicit C(bool v) noexcept;
Postconditions:
value() == v.
C& operator=(bool v) noexcept;
Returns:
*this.
Postconditions:
value() == v.
bool value() const noexcept;
Returns: The stored socket option value. For extensible implementations, returns
value_ != 0.
explicit operator bool() const noexcept;
Returns:
value().
bool operator!() const noexcept;
Returns:
!value().
template<class Protocol> int level(const Protocol& p) const noexcept;
Returns:
L.
template<class Protocol> int name(const Protocol& p) const noexcept;
Returns:
N.
template<class Protocol> void* data(const Protocol& p) noexcept;
Returns:
std::addressof(value_).
template<class Protocol> const void* data(const Protocol& p) const noexcept;
Returns:
std::addressof(value_).
template<class Protocol> size_t size(const Protocol& p) const noexcept;
Returns:
sizeof(value_).
template<class Protocol> void resize(const Protocol& p, size_t s);
Throws:
length_errorifsis not a valid data size for the protocol specified byp.
            A type X meets the IntegerSocketOption requirements if
            it satisfies the requirements of Destructible
            (C++Std [destructible]), DefaultConstructible
            (C++Std [defaultconstructible]), CopyConstructible
            (C++Std [copyconstructible]), CopyAssignable
            (C++Std [copyassignable]), GettableSocketOption, and SettableSocketOption,
            as well as the additional requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            b denotes a (possibly
            const) value of type int,
            and u denotes an identifier.
          
Table 28. IntegerSocketOption requirements
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                      post:  | |
| 
                       | 
                      post:  | |
| 
                       | 
                       | Returns the current integer value of the socket option object. | 
            In this Technical Specification, types that satisfy the IntegerSocketOption requirements are
            defined as follows.
          
class C { public: // constructors: C() noexcept; explicit C(int v) noexcept; // members: C& operator=(int v) noexcept; int value() const noexcept; };
Extensible implementations provide the following member functions:
class C { public: template<class Protocol> int level(const Protocol& p) const noexcept; template<class Protocol> int name(const Protocol& p) const noexcept; template<class Protocol> void* data(const Protocol& p) noexcept; template<class Protocol> const void* data(const Protocol& p) const noexcept; template<class Protocol> size_t size(const Protocol& p) const noexcept; template<class Protocol> void resize(const Protocol& p, size_t s); // remainder unchanged private: int value_; // exposition only };
            Let L and N
            identify the POSIX macros to be passed as the level
            and option_name arguments, respectively, to POSIX
            setsockopt
            and getsockopt.
          
C() noexcept;
Postconditions:
!value().
explicit C(int v) noexcept;
Postconditions:
value() == v.
C& operator=(int v) noexcept;
Returns:
*this.
Postconditions:
value() == v.
int value() const noexcept;
Returns: The stored socket option value. For extensible implementations, returns
value_.
template<class Protocol> int level(const Protocol& p) const noexcept;
Returns:
L.
template<class Protocol> int name(const Protocol& p) const noexcept;
Returns:
N.
template<class Protocol> void* data(const Protocol& p) noexcept;
Returns:
std::addressof(value_).
template<class Protocol> const void* data(const Protocol& p) const noexcept;
Returns:
std::addressof(value_).
template<class Protocol> size_t size(const Protocol& p) const noexcept;
Returns:
sizeof(value_).
template<class Protocol> void resize(const Protocol& p, size_t s);
Throws:
length_errorifsis not a valid data size for the protocol specified byp.
[socket.reqmts.iocontrolcommand]
            A type X meets the IoControlCommand requirements if it
            satisfies the requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            and b denotes a value
            of type X.
          
Table 29. IoControlCommand requirements for extensible implementations
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | Returns a value suitable for passing as the request argument to POSIX ioctl (or equivalent). | 
| 
                       | 
                       | 
[socket.reqmts.connectcondition]
            A type X meets the ConnectCondition requirements if it
            satisfies the requirements of Destructible
            (C++Std [destructible]) and CopyConstructible
            (C++Std [copyconstructible]), as well as the additional requirements
            listed below.
          
            In the table below, x
            denotes a value of type X,
            ec denotes a (possibly
            const) value of type error_code,
            and ep denotes a (possibly
            const) value of some type satisfying the endpoint
            requirements.
          
Table 30. ConnectCondition requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | 
                      Returns  | 
const error_category& socket_category() noexcept;
Returns: A reference to an object of a type derived from class
error_category.
The object’s
default_error_conditionandequivalentvirtual functions behave as specified for the classerror_category. The object’snamevirtual function returns a pointer to the string"socket".
error_code make_error_code(socket_errc e) noexcept;
Returns:
error_code(static_cast<int>(e), socket_category()).
error_condition make_error_condition(socket_errc e) noexcept;
Returns:
error_condition(static_cast<int>(e), socket_category()).
namespace std { namespace experimental { namespace net { inline namespace v1 { class socket_base { public: class broadcast; class debug; class do_not_route; class keep_alive; class linger; class out_of_band_inline; class receive_buffer_size; class receive_low_watermark; class reuse_address; class send_buffer_size; class send_low_watermark; typedef T1 shutdown_type; static constexpr shutdown_type shutdown_receive; static constexpr shutdown_type shutdown_send; static constexpr shutdown_type shutdown_both; typedef T2 wait_type; static constexpr wait_type wait_read; static constexpr wait_type wait_write; static constexpr wait_type wait_error; typedef T3 message_flags; static constexpr message_flags message_peek; static constexpr message_flags message_out_of_band; static constexpr message_flags message_do_not_route; static const int max_listen_connections; protected: socket_base(); ~socket_base(); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          socket_base defines several
          member types:
        
          — socket option classes broadcast,
          debug, do_not_route,
          keep_alive, linger, out_of_band_inline,
          receive_buffer_size, receive_low_watermark, reuse_address, send_buffer_size,
          and send_low_watermark;
        
          — an enumerated type, shutdown_type,
          for use with the basic_socket<Protocol> class's shutdown
          member function.
        
          — an enumerated type, wait_type,
          for use with the basic_socket<Protocol> and basic_socket_acceptor<Protocol> classes' wait
          and async_wait member functions,
        
          — a bitmask type, message_flags,
          for use with the basic_stream_socket<Protocol> class's send,
          async_send,receive, and async_receive
          member functions, and the basic_datagram_socket<Protocol> class's send,
          async_send, send_to, async_send_to,
          receive, async_receive, receive_from,
          and async_receive_from
          member functions.
        
          — a constant, max_listen_connections,
          for use with the basic_socket_acceptor<Protocol> class's listen
          member function.
        
Table 31. socket_base constants
| Constant Name | POSIX macro | Definition or notes | 
|---|---|---|
| 
                     | 
                     | Disables further receive operations. | 
| 
                     | 
                     | Disables further send operations. | 
| 
                     | 
                     | Disables further send and receive operations. | 
| 
                     | 
                    Wait until the socket is ready-to-read. | |
| 
                     | 
                    Wait until the socket is ready-to-write. | |
| 
                     | 
                    Wait until the socket has a pending error condition. | |
| 
                     | 
                     | Leave received data in queue. | 
| 
                     | 
                     | Out-of-band data. | 
| 
                     | 
                     | Send without using routing tables. | 
| 
                     | 
                     | The implementation-defined limit on the length of the queue of pending incoming connections. | 
          In the table below, let C denote
          a socket option class; let L identify
          the POSIX macro to be passed as the level argument
          to POSIX setsockopt
          and getsockopt;
          let N identify the POSIX macro
          to be passed as the option_name argument to POSIX
          setsockopt
          and getsockopt;
          and let T identify the type of
          the value whose address will be passed as the option_value
          argument to POSIX setsockopt
          and getsockopt.
        
Table 32. socket options
| C | L | N | T | Requirements, definition or notes | 
|---|---|---|---|---|
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | Controls the behavior when a socket is closed and unsent data is present. | |
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
            The linger class represents
            a socket option for controlling the behavior when a socket is closed
            and unsent data is present.
          
namespace std { namespace experimental { namespace net { inline namespace v1 { class socket_base::linger { public: // constructors: linger() noexcept; linger(bool e, chrono::seconds t) noexcept; // members: bool enabled() const noexcept; void enabled(bool e) noexcept; chrono::seconds timeout() const noexcept; void timeout(chrono::seconds t) noexcept; }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
            linger satisfies the
            requirements of Destructible
            (C++Std [destructible]), DefaultConstructible
            (C++Std [defaultconstructible]), CopyConstructible
            (C++Std [copyconstructible]), CopyAssignable
            (C++Std [copyassignable]), GettableSocketOption, and SettableSocketOption.
          
Extensible implementations provide the following member functions:
namespace std { namespace experimental { namespace net { inline namespace v1 { class socket_base::linger { public: template<class Protocol> int level(const Protocol& p) const noexcept; template<class Protocol> int name(const Protocol& p) const noexcept; template<class Protocol> void data(const Protocol& p) noexcept; template<class Protocol> const void* data(const Protocol& p) const noexcept; template<class Protocol> size_t size(const Protocol& p) const noexcept; template<class Protocol> void resize(const Protocol& p, size_t s); // remainder unchanged private: ::linger value_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std linger() noexcept;
Postconditions:
!enabled() && timeout() == chrono::seconds(0).
linger(bool e, chrono::seconds t) noexcept;
Postconditions:
enabled() == e && timeout() == t.
bool enabled() const noexcept;
Returns:
value_.l_onoff != 0.
void enabled(bool e) noexcept;
Postconditions:
enabled() == e.
chrono::seconds timeout() const noexcept;
Returns:
chrono::seconds(value_.l_linger).
void timeout(chrono::seconds t) noexcept;
Postconditions:
timeout() == t.
template<class Protocol> int level(const Protocol& p) const noexcept;
Returns:
SOL_SOCKET.
template<class Protocol> int name(const Protocol& p) const noexcept;
Returns:
SO_LINGER.
template<class Protocol> void* data(const Protocol& p) const noexcept;
Returns:
std::addressof(value_).
template<class Protocol> const void* data(const Protocol& p) const noexcept;
Returns:
std::addressof(value_).
template<class Protocol> size_t size(const Protocol& p) const noexcept;
Returns:
sizeof(value_).
template<class Protocol> void resize(const Protocol& p, size_t s);
Throws:
length_errorifs != sizeof(value_).
          Class template basic_socket<Protocol> is used as the base class for the
          basic_datagram_socket<Protocol>
          and basic_stream_socket<Protocol> class templates. It provides functionality
          that is common to both types of socket.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Protocol> class basic_socket : public socket_base { public: // types: typedef io_context::executor_type executor_type; typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; // basic_socket operations: executor_type get_executor() noexcept; native_handle_type native_handle(); // See native handles void open(const protocol_type& protocol = protocol_type()); void open(const protocol_type& protocol, error_code& ec); void assign(const protocol_type& protocol, const native_handle_type& native_socket); // See native handles void assign(const protocol_type& protocol, const native_handle_type& native_socket, error_code& ec); // See native handles bool is_open() const noexcept; void close(); void close(error_code& ec); void cancel(); void cancel(error_code& ec); template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec); template<class GettableSocketOption> void get_option(GettableSocketOption& option) const; template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec) const; template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec); void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec); bool non_blocking() const; void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec); bool native_non_blocking() const; bool at_mark() const; bool at_mark(error_code& ec) const; size_t available() const; size_t available(error_code& ec) const; void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec); void shutdown(shutdown_type what); void shutdown(shutdown_type what, error_code& ec); endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const; endpoint_type remote_endpoint() const; endpoint_type remote_endpoint(error_code& ec) const; void connect(const endpoint_type& endpoint); void connect(const endpoint_type& endpoint, error_code& ec); template<class CompletionToken> DEDUCED async_connect(const endpoint_type& endpoint, CompletionToken&& token); void wait(wait_type w); void wait(wait_type w, error_code& ec); template<class CompletionToken> DEDUCED async_wait(wait_type w, CompletionToken&& token); protected: // construct / copy / destroy: explicit basic_socket(io_context& ctx); basic_socket(io_context& ctx, const protocol_type& protocol); basic_socket(io_context& ctx, const endpoint_type& endpoint); basic_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket); // See native handles basic_socket(const basic_socket&) = delete; basic_socket(basic_socket&& rhs); template<class OtherProtocol> basic_socket(basic_socket<OtherProtocol>&& rhs); ~basic_socket(); basic_socket& operator=(const basic_socket&) = delete; basic_socket& operator=(basic_socket&& rhs); template<class OtherProtocol> basic_socket& operator=(basic_socket<OtherProtocol>&& rhs); private: protocol_type protocol_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_socket
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), and MoveAssignable
          (C++Std [moveassignable]).
        
          When an operation has its effects specified as if by passing the result
          of native_handle()
          to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false
          at the point in the effects when the POSIX function is called.
        
explicit basic_socket(io_context& ctx);
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == false.
basic_socket(io_context& ctx, const protocol_type& protocol);
Effects: Opens this socket as if by calling
open(protocol).
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == true.
—non_blocking() == false.
—protocol_ == protocol.
basic_socket(io_context& ctx, const endpoint_type& endpoint);
Effects: Opens and binds this socket as if by calling:
open(endpoint.protocol()); bind(endpoint);
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == true.
—non_blocking() == false.
—protocol_ == endpoint.protocol().
basic_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket);
Requires:
native_socketis a native handle to an open socket.
Effects: Assigns the existing native socket into this socket as if by calling
assign(protocol, native_socket).
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == true.
—non_blocking() == false.
—protocol_ == protocol.
basic_socket(basic_socket&& rhs);
Effects: Move constructs an object of class
basic_socket<Protocol>that refers to the state originally represented byrhs.
Postconditions:
—get_executor()is equal to the prior value ofrhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the constructor invocation.
—non_blocking()returns the same value asrhs.non_blocking()prior to the constructor invocation.
—native_handle()returns the prior value ofrhs.native_handle().
—protocol_is the prior value ofrhs.protocol_.
—rhs.is_open() == false.
template<class OtherProtocol> basic_socket(basic_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: Move constructs an object of class
basic_socket<Protocol>that refers to the state originally represented byrhs.
Postconditions:
—get_executor()is equal to the prior value ofrhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the constructor invocation.
—non_blocking()returns the same value asrhs.non_blocking()prior to the constructor invocation.
—native_handle()returns the prior value ofrhs.native_handle().
—protocol_is the result of converting the prior value ofrhs.protocol_.
—rhs.is_open() == false.
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
~basic_socket();
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this socket, disables the linger socket option to prevent the destructor from blocking, and releases socket resources as if by POSIXclose(native_handle()). Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
basic_socket& operator=(basic_socket&& rhs);
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue. Disables the linger socket option to prevent the assignment from blocking, and releases socket resources as if by POSIXclose(native_handle()). Moves into*thisthe state originally represented byrhs.
Postconditions:
—get_executor()is equal to the prior value ofrhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the assignment.
—non_blocking()returns the same value asrhs.non_blocking()prior to the assignment.
—protocol_is the prior value ofrhs.protocol_.
—rhs.is_open() == false.
Returns:
*this.
template<class OtherProtocol> basic_socket& operator=(basic_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue. Disables the linger socket option to prevent the assignment from blocking, and releases socket resources as if by POSIXclose(native_handle()). Moves into*thisthe state originally represented byrhs.
Postconditions:
—get_executor()is equal to the prior value ofrhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the assignment.
—non_blocking()returns the same value asrhs.non_blocking()prior to the assignment.
—protocol_is the result of converting the prior value ofrhs.protocol_.
—rhs.is_open() == false.
Returns:
*this.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
executor_type get_executor() noexcept;
Returns: The associated executor.
native_handle_type native_handle();
Returns: The native representation of this socket.
void open(const protocol_type& protocol); void open(const protocol_type& protocol, error_code& ec);
Effects: Establishes the postcondition, as if by POSIX
socket(protocol.family(), protocol.type(), protocol.protocol()).
Postconditions:
—is_open() == true.
—non_blocking() == false.
—protocol_ == protocol.
Error conditions:
—socket_errc::already_open— ifis_open() == true.
void assign(const protocol_type& protocol, const native_handle_type& native_socket); void assign(const protocol_type& protocol, const native_handle_type& native_socket, error_code& ec);
Requires:
native_socketis a native handle to an open socket.
Effects: Assigns the native socket handle to this socket object.
Postconditions:
—is_open() == true.
—non_blocking() == false.
—protocol_ == protocol.
Error conditions:
—socket_errc::already_open— ifis_open() == true.
bool is_open() const noexcept;
Returns: A
boolindicating whether this socket was opened by a previous call toopenorassign.
void close(); void close(error_code& ec);
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this socket, and establishes the postcondition as if by POSIXclose(native_handle()). Completion handlers for canceled asynchronous operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
Postconditions:
is_open() == false.
void cancel(); void cancel(error_code& ec);
Effects: Cancels all outstanding asynchronous operations associated with this socket. Completion handlers for canceled asynchronous operations are passed an error code
ecsuch thatec == errc::operation_canceledyieldstrue.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec);
Effects: Sets an option on this socket, as if by POSIX
setsockopt(native_handle(), option.level(protocol_), option.name(protocol_), option.data(protocol_), option.size(protocol_)).
template<class GettableSocketOption> void get_option(GettableSocketOption& option); template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec);
Effects: Gets an option from this socket, as if by POSIX:
socklen_t option_len = option.size(protocol_); int result = getsockopt(native_handle(), option.level(protocol_), option.name(protocol_), option.data(protocol_), &option_len); if (result == 0) option.resize(option_len);
template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec);
Effects: Executes an I/O control command on this socket, as if by POSIX
ioctl(native_handle(), command.name(), command.data()).
void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec);
Effects: Sets the non-blocking mode of this socket. The non-blocking mode determines whether subsequent synchronous socket operations on
*thisblock the calling thread.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
Postconditions:
non_blocking() == mode.
[Note: The non-blocking mode has no effect on the behavior of asynchronous operations. —end note]
bool non_blocking() const;
Returns: The non-blocking mode of this socket.
void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec);
Effects: Sets the non-blocking mode of the underlying native socket, as if by POSIX:
int flags = fcntl(native_handle(), F_GETFL, 0); if (flags >= 0) { if (mode) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; fcntl(native_handle(), F_SETFL, flags); }
The native non-blocking mode has no effect on the behavior of the synchronous or asynchronous operations specified in this clause.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
—errc::invalid_argument— ifmode == falseandnon_blocking() == true. [Note: As the combination does not make sense. —end note]
bool native_non_blocking() const;
Returns: The non-blocking mode of the underlying native socket.
Remarks: Implementations are permitted and encouraged to cache the native non-blocking mode that was applied through a prior call to
native_non_blocking. Implementations may return an incorrect value if a program sets the non-blocking mode directly on the socket, by calling an operating system-specific function on the result ofnative_handle().
bool at_mark() const; bool at_mark(error_code& ec) const;
Effects: Determines if this socket is at the out-of-band data mark, as if by POSIX
sockatmark(native_handle()). [Note: Theat_mark()function must be used in conjunction with thesocket_base::out_of_band_inlinesocket option. —end note]
Returns: A
boolindicating whether this socket is at the out-of-band data mark.
size_t available() const; size_t available(error_code& ec) const;
Returns: An indication of the number of bytes that may be read without blocking, or 0 if an error occurs.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec);
Effects: Binds this socket to the specified local endpoint, as if by POSIX
bind(native_handle(), endpoint.data(), endpoint.size()).
void shutdown(shutdown_type what); void shutdown(shutdown_type what, error_code& ec);
Effects: Shuts down all or part of a full-duplex connection for the socket, as if by POSIX
shutdown(native_handle(), static_cast<int>(what)).
endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const;
Effects: Determines the locally-bound endpoint associated with the socket, as if by POSIX:
endpoint_type endpoint; socklen_t endpoint_len = endpoint.capacity(); int result == getsockname(native_handle(), endpoint.data(), &endpoint_len); if (result == 0) endpoint.resize(endpoint_len);
Returns: On success,
endpoint. Otherwiseendpoint_type().
endpoint_type remote_endpoint() const; endpoint_type remote_endpoint(error_code& ec) const;
Effects: Determines the remote endpoint associated with this socket, as if by POSIX:
endpoint_type endpoint; socklen_t endpoint_len = endpoint.capacity(); int result == getpeername(native_handle(), endpoint.data(), &endpoint_len); if (result == 0) endpoint.resize(endpoint_len);
Returns: On success,
endpoint. Otherwiseendpoint_type().
void connect(const endpoint_type& endpoint); void connect(const endpoint_type& endpoint, error_code& ec);
Effects: If
is_open()isfalse, opens this socket by performingopen(endpoint.protocol(), ec). Ifec, returns with no further action. Connects this socket to the specified remote endpoint, as if by POSIXconnect(native_handle(), endpoint.data(), endpoint.size()).
template<class CompletionToken> DEDUCED async_connect(const endpoint_type& endpoint, CompletionToken&& token);
Completion signature:
void(error_code ec).
Effects: If
is_open()isfalse, opens this socket by performingopen(endpoint.protocol(), ec). Ifec, the operation completes immediately with no further action. Initiates an asynchronous operation to connect this socket to the specified remote endpoint, as if by POSIXconnect(native_handle(), endpoint.data(), endpoint.size()).
When an asynchronous connect operation on this socket is simultaneously outstanding with another asynchronous connect, read, or write operation on this socket, the behavior is undefined.
If a program performs a synchronous operation on this socket, other than
closeorcancel, while there is an outstanding asynchronous connect operation, the behavior is undefined.
void wait(wait_type w); void wait(wait_type w, error_code& ec);
Effects: Waits for this socket to be ready to read, ready to write, or to have error conditions pending, as if by POSIX poll.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
template<class CompletionToken> DEDUCED async_wait(wait_type w, CompletionToken&& token);
Completion signature:
void(error_code ec).
Effects: Initiates an asynchronous operation to wait for this socket to be ready to read, ready to write, or to have error conditions pending, as if by POSIX poll.
When there are multiple outstanding asynchronous wait operations on this socket with the same
wait_typevalue, all of these operations complete when this socket enters the corresponding ready state. The order of invocation of the completion handlers for these operations is unspecified.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
          The class template basic_datagram_socket<Protocol> is used to send and receive discrete
          messages of fixed maximum length.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Protocol> class basic_datagram_socket : public basic_socket<Protocol> { public: // types: typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; // construct / copy / destroy: explicit basic_datagram_socket(io_context& ctx); basic_datagram_socket(io_context& ctx, const protocol_type& protocol); basic_datagram_socket(io_context& ctx, const endpoint_type& endpoint); basic_datagram_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket); basic_datagram_socket(const basic_datagram_socket&) = delete; basic_datagram_socket(basic_datagram_socket&& rhs); template<class OtherProtocol> basic_datagram_socket(basic_datagram_socket<OtherProtocol>&& rhs); ~basic_datagram_socket(); basic_datagram_socket& operator=(const basic_datagram_socket&) = delete; basic_datagram_socket& operator=(basic_datagram_socket&& rhs); template<class OtherProtocol> basic_datagram_socket& operator=(basic_datagram_socket<OtherProtocol>&& rhs); // basic_datagram_socket operations: template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, CompletionToken&& token); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, error_code& ec); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, error_code& ec); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, CompletionToken&& token); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, CompletionToken&& token); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, CompletionToken&& token); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, error_code& ec); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, error_code& ec); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, CompletionToken&& token); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, CompletionToken&& token); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_datagram_socket
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), and MoveAssignable
          (C++Std [moveassignable]).
        
          If a program performs a synchronous operation on this socket, other than
          close, cancel,
          shutdown, send, or send_to,
          while there is an outstanding asynchronous read operation, the behavior
          is undefined.
        
          If a program performs a synchronous operation on this socket, other than
          close, cancel,
          shutdown, receive, or receive_from,
          while there is an outstanding asynchronous write operation, the behavior
          is undefined.
        
          When an operation has its effects specified as if by passing the result
          of native_handle()
          to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false
          at the point in the effects when the POSIX function is called.
        
explicit basic_datagram_socket(io_context& ctx);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx).
basic_datagram_socket(io_context& ctx, const protocol_type& protocol);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx, protocol).
basic_datagram_socket(io_context& ctx, const endpoint_type& endpoint);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx, endpoint).
basic_datagram_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx, protocol, native_socket).
basic_datagram_socket(basic_datagram_socket&& rhs);
Effects: Move constructs an object of class
basic_datagram_socket<Protocol>, initializing the base class withbasic_socket<Protocol>(std::move(rhs)).
template<class OtherProtocol> basic_datagram_socket(basic_datagram_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: Move constructs an object of class
basic_datagram_socket<Protocol>, initializing the base class withbasic_socket<Protocol>(std::move(rhs)).
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
basic_datagram_socket& operator=(basic_datagram_socket&& rhs);
Effects: Equivalent to
basic_socket<Protocol>::operator=(std::move(rhs)).
Returns:
*this.
template<class OtherProtocol> basic_datagram_socket& operator=(basic_datagram_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: Equivalent to
basic_socket<Protocol>::operator=(std::move(rhs)).
Returns:
*this.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec);
Returns:
receive(buffers, socket_base::message_flags(), ec).
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, and reads data from this socket as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; recvmsg(native_handle(), &message, static_cast<int>(flags));
Returns: On success, the number of bytes received. Otherwise
0.
[Note: This operation may be used with connection-mode or connectionless-mode sockets, but it is normally used with connection-mode sockets because it does not permit the application to retrieve the source endpoint of received data. —end note]
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, CompletionToken&& token);
Returns:
async_receive(buffers, socket_base::message_flags(), forward<CompletionToken>(token)).
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to read data from this socket. Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, then reads data as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; recvmsg(native_handle(), &message, static_cast<int>(flags));
If the operation completes successfully,
nis the number of bytes received. Otherwisenis0.
[Note: This operation may be used with connection-mode or connectionless-mode sockets, but it is normally used with connection-mode sockets because it does not permit the application to retrieve the source endpoint of received data. —end note]
Error conditions:
—errc::invalid_argument— ifsocket_base::message_peekis set in flags.
template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, error_code& ec);
Returns:
receive_from(buffers, endpoint, socket_base::message_flags(), ec).
template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, error_code& ec);
Effects: Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, and reads data from this socket as if by POSIX:msghdr message; message.msg_name = sender.data(); message.msg_namelen = sender.capacity(); message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; ssize_t result = recvmsg(native_handle(), &message, static_cast<int>(flags)); if (result >= 0) sender.resize(message.msg_namelen);
Returns: On success, the number of bytes received. Otherwise
0.
[Note: This operation may be used with connection-mode or connectionless-mode sockets, but it is normally used with connectionless-mode sockets because it permits the application to retrieve the source endpoint of received data. —end note]
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, CompletionToken&& token);
Effects: Returns
async_receive_from(buffers, sender, socket_base::message_flags(), forward<CompletionToken>(token)).
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to read data from this socket. Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, then reads data as if by POSIX:msghdr message; message.msg_name = sender.data(); message.msg_namelen = sender.capacity(); message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; ssize_t result = recvmsg(native_handle(), &message, static_cast<int>(flags)); if (result >= 0) sender.resize(message.msg_namelen);
If the operation completes successfully,
nis the number of bytes received. Otherwisenis0.
[Note: This operation may be used with connection-mode or connectionless-mode sockets, but it is normally used with connectionless-mode sockets because it permits the application to retrieve the source endpoint of received data. —end note]
Error conditions:
—errc::invalid_argument— ifsocket_base::message_peekis set in flags.
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec);
Returns:
send(buffers, socket_base::message_flags(), ec).
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, and writes data to this socket as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; sendmsg(native_handle(), &message, static_cast<int>(flags));
Returns: On success, the number of bytes sent. Otherwise
0.
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, CompletionToken&& token);
Returns:
async_send(buffers, socket_base::message_flags(), forward<CompletionToken>(token)).
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to write data to this socket. Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, then writes data as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; sendmsg(native_handle(), &message, static_cast<int>(flags));
If the operation completes successfully,
nis the number of bytes sent. Otherwisenis0.
template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, error_code& ec);
Returns:
send_to(buffers, destination, socket_base::message_flags(), ec).
template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, socket_base::message_flags flags, error_code& ec);
Effects: Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, and writes data to this socket as if by POSIX:msghdr message; message.msg_name = sender.data(); message.msg_namelen = sender.size(); message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; sendmsg(native_handle(), &message, static_cast<int>(flags));
Returns: On success, the number of bytes sent. Otherwise
0.
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, CompletionToken&& token);
Returns:
async_send_to(buffers, recipient, socket_base::message_flags(), forward<CompletionToken>(token)).
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send_to(const ConstBufferSequence& buffers, const endpoint_type& recipient, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to write data to this socket. Constructs an array
iovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, then writes data as if by POSIX:msghdr message; message.msg_name = sender.data(); message.msg_namelen = sender.size(); message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; sendmsg(native_handle(), &message, static_cast<int>(flags));
If the operation completes successfully,
nis the number of bytes sent. Otherwisenis0.
          The class template basic_stream_socket<Protocol> is used to exchange data with a peer
          over a sequenced, reliable, bidirectional, connection-mode byte stream.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Protocol> class basic_stream_socket : public basic_socket<Protocol> { public: // types: typedef implementation defined native_handle_type; // See native handles typedef Protocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; // construct / copy / destroy: explicit basic_stream_socket(io_context& ctx); basic_stream_socket(io_context& ctx, const protocol_type& protocol); basic_stream_socket(io_context& ctx, const endpoint_type& endpoint); basic_stream_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket); basic_stream_socket(const basic_stream_socket&) = delete; basic_stream_socket(basic_stream_socket&& rhs); template<class OtherProtocol> basic_stream_socket(basic_stream_socket<OtherProtocol>&& rhs); ~basic_stream_socket(); basic_stream_socket& operator=(const basic_stream_socket&) = delete; basic_stream_socket& operator=(basic_stream_socket&& rhs); template<class OtherProtocol> basic_stream_socket& operator=(basic_stream_socket<OtherProtocol>&& rhs); // basic_stream_socket operations: template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, CompletionToken&& token); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, CompletionToken&& token); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers, error_code& ec); template<class MutableBufferSequence, class CompletionToken> DEDUCED async_read_some(const MutableBufferSequence& buffers, CompletionToken&& token); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers, error_code& ec); template<class ConstBufferSequence, class CompletionToken> DEDUCED async_write_some(const ConstBufferSequence& buffers, CompletionToken&& token); }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_stream_socket
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), MoveAssignable
          (C++Std [moveassignable]), SyncReadStream, SyncWriteStream, AsyncReadStream, and AsyncWriteStream.
        
          If a program performs a synchronous operation on this socket, other than
          close, cancel,
          shutdown, or send, while there is an outstanding asynchronous
          read operation, the behavior is undefined.
        
          If a program performs a synchronous operation on this socket, other than
          close, cancel,
          shutdown, or receive, while there is an outstanding
          asynchronous write operation, the behavior is undefined.
        
          When an operation has its effects specified as if by passing the result
          of native_handle()
          to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false
          at the point in the effects when the POSIX function is called.
        
explicit basic_stream_socket(io_context& ctx);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx).
basic_stream_socket(io_context& ctx, const protocol_type& protocol);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx, protocol).
basic_stream_socket(io_context& ctx, const endpoint_type& endpoint);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx, endpoint).
basic_stream_socket(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_socket);
Effects: Initializes the base class with
basic_socket<Protocol>(ctx, protocol, native_socket).
basic_stream_socket(basic_stream_socket&& rhs);
Effects: Move constructs an object of class
basic_stream_socket<Protocol>, initializing the base class withbasic_socket<Protocol>(std::move(rhs)).
template<class OtherProtocol> basic_stream_socket(basic_stream_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: Move constructs an object of class
basic_stream_socket<Protocol>, initializing the base class withbasic_socket<Protocol>(std::move(rhs)).
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
basic_stream_socket& operator=(basic_stream_socket&& rhs);
Effects: Equivalent to
basic_socket<Protocol>::operator=(std::move(rhs)).
Returns:
*this.
template<class OtherProtocol> basic_stream_socket& operator=(basic_stream_socket<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: Equivalent to
basic_socket<Protocol>::operator=(std::move(rhs)).
Returns:
*this.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, error_code& ec);
Returns:
receive(buffers, socket_base::message_flags(), ec).
template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags); template<class MutableBufferSequence> size_t receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: If
buffer_size(buffers) == 0, returns immediately with no error. Otherwise, constructs an arrayiovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, and reads data from this socket as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; recvmsg(native_handle(), &message, static_cast<int>(flags));
Returns: On success, the number of bytes received. Otherwise
0.
Error conditions:
—stream_errc::eof— if there is no data to be received and the peer performed an orderly shutdown.
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, CompletionToken&& token);
Returns:
async_receive(buffers, socket_base::message_flags(), forward<CompletionToken>(token)).
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to read data from this socket. If
buffer_size(buffers) == 0, the asynchronous operation completes immediately with no error andn == 0. Otherwise, constructs an arrayiovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, then reads data as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; recvmsg(native_handle(), &message, static_cast<int>(flags));
If the operation completes successfully,
nis the number of bytes received. Otherwisenis0.
Error conditions:
—errc::invalid_argument— ifsocket_base::message_peekis set in flags. —stream_errc::eof— if there is no data to be received and the peer performed an orderly shutdown.
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, error_code& ec);
Returns:
send(buffers, socket_base::message_flags(), ec).
template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags); template<class ConstBufferSequence> size_t send(const ConstBufferSequence& buffers, socket_base::message_flags flags, error_code& ec);
Effects: If
buffer_size(buffers) == 0, returns immediately with no error. Otherwise, constructs an arrayiovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, and writes data to this socket as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; sendmsg(native_handle(), &message, static_cast<int>(flags));
Returns: On success, the number of bytes sent. Otherwise
0.
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, CompletionToken&& token);
Returns:
async_send(buffers, socket_base::message_flags(), forward<CompletionToken>(token)).
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, CompletionToken&& token);
Completion signature:
void(error_code ec, size_t n).
Effects: Initiates an asynchronous operation to write data to this socket. If
buffer_size(buffers) == 0, the asynchronous operation completes immediately with no error andn == 0. Otherwise, constructs an arrayiovof POSIX typestruct iovecand lengthiovlen, corresponding tobuffers, then writes data as if by POSIX:msghdr message; message.msg_name = nullptr; message.msg_namelen = 0; message.msg_iov = iov; message.msg_iovlen = iovlen; message.msg_control = nullptr; message.msg_controllen = 0; message.msg_flags = 0; sendmsg(native_handle(), &message, static_cast<int>(flags));
If the operation completes successfully,
nis the number of bytes sent. Otherwisenis0.
template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers); template<class MutableBufferSequence> size_t read_some(const MutableBufferSequence& buffers, error_code& ec);
Returns:
receive(buffers, ec).
template<class MutableBufferSequence, class CompletionToken> DEDUCED async_read_some(const MutableBufferSequence& buffers, CompletionToken&& token);
Returns:
async_receive(buffers, forward<CompletionToken>(token)).
template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers); template<class ConstBufferSequence> size_t write_some(const ConstBufferSequence& buffers, error_code& ec);
Returns:
send(buffers, ec).
template<class ConstBufferSequence, class CompletionToken> DEDUCED async_write_some(const ConstBufferSequence& buffers, CompletionToken&& token);
Returns:
async_send(buffers, forward<CompletionToken>(token)).
          An object of class template basic_socket_acceptor<AcceptableProtocol> is used to listen for, and queue, incoming
          socket connections. Socket objects that represent the incoming connections
          are dequeued by calling accept
          or async_accept.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class AcceptableProtocol> class basic_socket_acceptor : public socket_base { public: // types: typedef io_context::executor_type executor_type; typedef implementation defined native_handle_type; // See native handles typedef AcceptableProtocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; typedef typename protocol_type::socket socket_type; // construct / copy / destroy: explicit basic_socket_acceptor(io_context& ctx); basic_socket_acceptor(io_context& ctx, const protocol_type& protocol); basic_socket_acceptor(io_context& ctx, const endpoint_type& endpoint, bool reuse_addr = true); basic_socket_acceptor(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_acceptor); basic_socket_acceptor(const basic_socket_acceptor&) = delete; basic_socket_acceptor(basic_socket_acceptor&& rhs); template<class OtherProtocol> basic_socket_acceptor(basic_socket_acceptor<OtherProtocol>&& rhs); ~basic_socket_acceptor(); basic_socket_acceptor& operator=(const basic_socket_acceptor&) = delete; basic_socket_acceptor& operator=(basic_socket_acceptor&& rhs); template<class OtherProtocol> basic_socket_acceptor& operator=(basic_socket_acceptor<OtherProtocol>&& rhs); // basic_socket_acceptor operations: executor_type get_executor() noexcept; native_handle_type native_handle(); // See native handles void open(const protocol_type& protocol = protocol_type()); void open(const protocol_type& protocol, error_code& ec); void assign(const protocol_type& protocol, const native_handle_type& native_acceptor); // See native handles void assign(const protocol_type& protocol, const native_handle_type& native_acceptor, error_code& ec); // See native handles bool is_open() const; void close(); void close(error_code& ec); void cancel(); void cancel(error_code& ec); template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec); template<class GettableSocketOption> void get_option(GettableSocketOption& option) const; template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec) const; template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec); void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec); bool non_blocking() const; void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec); bool native_non_blocking() const; void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec); void listen(int backlog = max_listen_connections); void listen(int backlog, error_code& ec); endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const; void enable_connection_aborted(bool mode); bool enable_connection_aborted() const; socket_type accept(); socket_type accept(error_code& ec); socket_type accept(io_context& ctx); socket_type accept(io_context& ctx, error_code& ec); template<class CompletionToken> DEDUCED async_accept(CompletionToken&& token); template<class CompletionToken> DEDUCED async_accept(io_context& ctx, CompletionToken&& token); socket_type accept(endpoint_type& endpoint); socket_type accept(endpoint_type& endpoint, error_code& ec); socket_type accept(io_context& ctx, endpoint_type& endpoint); socket_type accept(io_context& ctx, endpoint_type& endpoint, error_code& ec); template<class CompletionToken> DEDUCED async_accept(endpoint_type& endpoint, CompletionToken&& token); template<class CompletionToken> DEDUCED async_accept(io_context& ctx, endpoint_type& endpoint, CompletionToken&& token); void wait(wait_type w); void wait(wait_type w, error_code& ec); template<class CompletionToken> DEDUCED async_wait(wait_type w, CompletionToken&& token); private: protocol_type protocol_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_socket_acceptor
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), and MoveAssignable
          (C++Std [moveassignable]).
        
When there are multiple outstanding asynchronous accept operations the order in which the incoming connections are dequeued, and the order of invocation of the completion handlers for these operations, is unspecified.
          When an operation has its effects specified as if by passing the result
          of native_handle()
          to a POSIX function, then the operation fails with error condition errc::bad_file_descriptor if is_open() == false
          at the point in the effects when the POSIX function is called.
        
explicit basic_socket_acceptor(io_context& ctx);
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == false.
basic_socket_acceptor(io_context& ctx, const protocol_type& protocol);
Effects: Opens this acceptor as if by calling
open(protocol).
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == true.
—non_blocking() == false.
—enable_connection_aborted() == false.
—protocol_ == protocol.
basic_socket_acceptor(io_context& ctx, const endpoint_type& endpoint, bool reuse_addr = true);
Effects: Opens and binds this acceptor as if by calling:
open(endpoint.protocol()); if (reuse_addr) set_option(reuse_address(true)); bind(endpoint); listen();
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == true.
—non_blocking() == false.
—enable_connection_aborted() == false.
—protocol_ == endpoint.protocol().
basic_socket_acceptor(io_context& ctx, const protocol_type& protocol, const native_handle_type& native_acceptor);
Requires:
native_acceptoris a native handle to an open acceptor.
Effects: Assigns the existing native acceptor into this acceptor as if by calling
assign(protocol, native_acceptor).
Postconditions:
—get_executor() == ctx.get_executor().
—is_open() == true.
—non_blocking() == false.
—enable_connection_aborted() == false.
—protocol_ == protocol.
basic_socket_acceptor(basic_socket_acceptor&& rhs);
Effects: Move constructs an object of class
basic_socket_acceptor<AcceptableProtocol>that refers to the state originally represented byrhs.
Postconditions:
—get_executor() == rhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the constructor invocation.
—non_blocking()returns the same value asrhs.non_blocking()prior to the constructor invocation.
—enable_connection_aborted()returns the same value asrhs.enable_connection_aborted()prior to the constructor invocation.
—protocol_is equal to the prior value ofrhs.protocol_.
—rhs.is_open() == false.
template<class OtherProtocol> basic_socket_acceptor(basic_socket_acceptor<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: Move constructs an object of class
basic_socket_acceptor<AcceptableProtocol>that refers to the state originally represented byrhs.
Postconditions:
—get_executor() == rhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the constructor invocation.
—non_blocking()returns the same value asrhs.non_blocking()prior to the constructor invocation.
—enable_connection_aborted()returns the same value asrhs.enable_connection_aborted()prior to the constructor invocation.
—native_handle()returns the prior value ofrhs.native_handle().
—protocol_is the result of converting the prior value ofrhs.protocol_.
—rhs.is_open() == false.
Remarks: This constructor shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
~basic_socket_acceptor();
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this acceptor, and releases acceptor resources as if by POSIXclose(native_handle()). Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
basic_socket_acceptor& operator=(basic_socket_acceptor&& rhs);
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this acceptor, and releases acceptor resources as if by POSIXclose(native_handle()). Then moves into*thisthe state originally represented byrhs. Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
Postconditions:
—get_executor() == rhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the assignment.
—non_blocking()returns the same value asrhs.non_blocking()prior to the assignment.
—enable_connection_aborted()returns the same value asrhs.enable_connection_aborted()prior to the assignment.
—native_handle()returns the same value asrhs.native_handle()prior to the assignment.
—protocol_is the same value asrhs.protocol_prior to the assignment.
—rhs.is_open() == false.
Returns:
*this.
template<class OtherProtocol> basic_socket_acceptor& operator=(basic_socket_acceptor<OtherProtocol>&& rhs);
Requires:
OtherProtocolis implicitly convertible toProtocol.
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this acceptor, and releases acceptor resources as if by POSIXclose(native_handle()). Then moves into*thisthe state originally represented byrhs. Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
Postconditions:
—get_executor() == rhs.get_executor().
—is_open()returns the same value asrhs.is_open()prior to the assignment.
—non_blocking()returns the same value asrhs.non_blocking()prior to the assignment.
—enable_connection_aborted()returns the same value asrhs.enable_connection_aborted()prior to the assignment.
—native_handle()returns the same value asrhs.native_handle()prior to the assignment.
—protocol_is the result of converting the value ofrhs.protocol_prior to the assignment.
—rhs.is_open() == false.
Returns:
*this.
Remarks: This assignment operator shall not participate in overload resolution unless
OtherProtocolis implicitly convertible toProtocol.
executor_type get_executor() noexcept;
Returns: The associated executor.
native_handle_type native_handle();
Returns: The native representation of this acceptor.
void open(const protocol_type& protocol); void open(const protocol_type& protocol, error_code& ec);
Effects: Establishes the postcondition, as if by POSIX
socket(protocol.family(), protocol.type(), protocol.protocol()).
Postconditions:
—is_open() == true.
—non_blocking() == false.
—enable_connection_aborted() == false.
—protocol_ == protocol.
Error conditions:
—socket_errc::already_open— ifis_open()istrue.
void assign(const protocol_type& protocol, const native_handle_type& native_acceptor); void assign(const protocol_type& protocol, const native_handle_type& native_acceptor, error_code& ec);
Requires:
native_acceptoris a native handle to an open acceptor.
Effects: Assigns the native acceptor handle to this acceptor object.
Postconditions:
—is_open() == true.
—non_blocking() == false.
—enable_connection_aborted() == false.
—protocol_ == protocol.
Error conditions:
—socket_errc::already_open— ifis_open()istrue.
bool is_open() const;
Returns: A
boolindicating whether this acceptor was opened by a previous call toopenorassign.
void close(); void close(error_code& ec);
Effects: If
is_open()istrue, cancels all outstanding asynchronous operations associated with this acceptor, and establishes the postcondition as if by POSIXclose(native_handle()). Completion handlers for canceled asynchronous operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
Postconditions:
is_open() == false.
void cancel(); void cancel(error_code& ec);
Effects: Cancels all outstanding asynchronous operations associated with this acceptor. Completion handlers for canceled asynchronous operations are passed an error code
ecsuch thatec == errc::operation_canceledyieldstrue.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
—errc::operation_not_supported— Current conditions do not permit cancelation. The conditions under which cancelation of asynchronous operations is permitted are implementation-defined.
template<class SettableSocketOption> void set_option(const SettableSocketOption& option); template<class SettableSocketOption> void set_option(const SettableSocketOption& option, error_code& ec);
Effects: Sets an option on this acceptor, as if by POSIX
setsockopt(native_handle(), option.level(protocol_), option.name(protocol_), option.data(protocol_), option.size(protocol_)).
template<class GettableSocketOption> void get_option(GettableSocketOption& option); template<class GettableSocketOption> void get_option(GettableSocketOption& option, error_code& ec);
Effects: Gets an option from this acceptor, as if by POSIX:
socklen_t option_len = option.size(protocol_); int result = getsockopt(native_handle(), option.level(protocol_), option.name(protocol_), option.data(protocol_), &option_len); if (result == 0) option.resize(option_len);
template<class IoControlCommand> void io_control(IoControlCommand& command); template<class IoControlCommand> void io_control(IoControlCommand& command, error_code& ec);
Effects: Executes an I/O control command on this acceptor, as if by POSIX
ioctl(native_handle(), command.name(), command.data()).
void non_blocking(bool mode); void non_blocking(bool mode, error_code& ec);
Effects: Sets the non-blocking mode of this acceptor. The non-blocking mode determines whether subsequent synchronous socket operations on
*thisblock the calling thread.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
Postconditions:
non_blocking() == mode.
[Note: The non-blocking mode has no effect on the behavior of asynchronous operations. —end note]
bool non_blocking() const;
Returns: The non-blocking mode of this acceptor.
void native_non_blocking(bool mode); void native_non_blocking(bool mode, error_code& ec);
Effects: Sets the non-blocking mode of the underlying native acceptor, as if by POSIX:
int flags = fcntl(native_handle(), F_GETFL, 0); if (flags >= 0) { if (mode) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; fcntl(native_handle(), F_SETFL, flags); }
The native non-blocking mode has no effect on the behavior of the synchronous or asynchronous operations specified in this clause.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
—errc::invalid_argument— ifmode == falseandnon_blocking() == true. [Note: As the combination does not make sense. —end note]
bool native_non_blocking() const;
Returns: The non-blocking mode of the underlying native acceptor.
Remarks: Implementations are permitted and encouraged to cache the native non-blocking mode that was applied through a prior call to
native_non_blocking. Implementations may return an incorrect value if a program sets the non-blocking mode directly on the acceptor, by calling an operating system-specific function on the result ofnative_handle().
void bind(const endpoint_type& endpoint); void bind(const endpoint_type& endpoint, error_code& ec);
Effects: Binds this acceptor to the specified local endpoint, as if by POSIX
bind(native_handle(), endpoint.data(), endpoint.size()).
void listen(int backlog = socket_base::max_connections); void listen(int backlog, error_code& ec);
Effects: Marks this acceptor as ready to accept connections, as if by POSIX
listen(native_handle(), backlog).
endpoint_type local_endpoint() const; endpoint_type local_endpoint(error_code& ec) const;
Effects: Determines the locally-bound endpoint associated with this acceptor, as if by POSIX:
endpoint_type endpoint; socklen_t endpoint_len = endpoint.capacity(); int result == getsockname(native_handle(), endpoint.data(), &endpoint_len); if (result == 0) endpoint.resize(endpoint_len);
Returns: On success,
endpoint. Otherwiseendpoint_type().
void enable_connection_aborted(bool mode);
Effects: If
modeis true, subsequent synchronous or asynchronous accept operations on this acceptor are permitted to fail with error conditionerrc::connection_aborted. Ifmodeisfalse, subsequent accept operations will not fail witherrc::connection_aborted. [Note: Ifmodeisfalse, the implementation will restart the call to POSIX accept if it fails withECONNABORTED. —end note]
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
bool enable_connection_aborted() const;
Returns: Whether accept operations on this acceptor are permitted to fail with
errc::connection_aborted.
socket_type accept(); socket_type accept(error_code& ec);
Returns:
accept(get_executor().context(), ec).
socket_type accept(io_context& ctx); socket_type accept(io_context& ctx, error_code& ec);
Effects: Extracts a socket from the queue of pending connections of the acceptor, as if by POSIX:
native_handle_type h = accept(native_handle(), nullptr, 0);
Returns: If
his an open native socket,socket_type(ctx, s); otherwisesocket_type(ctx).
template<class CompletionToken> DEDUCED async_accept(CompletionToken&& token);
Returns:
async_accept(get_executor().context(), forward<CompletionToken>(token)).
template<class CompletionToken> DEDUCED async_accept(io_context& ctx, CompletionToken&& token);
Completion signature:
void(error_code ec, socket_type s).
Effects: Initiates an asynchronous operation to extract a socket from the queue of pending connections of the acceptor, as if by POSIX:
native_handle_type h = accept(native_handle(), nullptr, 0);On success,
sissocket_type(ctx, h). Otherwise,sissocket_type(ctx)`.
socket_type accept(endpoint_type& endpoint); socket_type accept(endpoint_type& endpoint, error_code& ec);
Returns:
accept(get_executor().context(), endpoint, ec).
socket_type accept(io_context& ctx, endpoint_type& endpoint); socket_type accept(io_context& ctx, endpoint_type& endpoint, error_code& ec);
Effects: Extracts a socket from the queue of pending connections of the acceptor, as if by POSIX:
socklen_t endpoint_len = endpoint.capacity(); native_handle_type h = accept(native_handle(), endpoint.data(), &endpoint_len); if (h >= 0) endpoint.resize(endpoint_len);
Returns: If
his an open native socket,socket_type(ctx, s); otherwisesocket_type(ctx).
template<class CompletionToken> DEDUCED async_accept(endpoint_type& endpoint, CompletionToken&& token);
Returns:
async_accept(get_executor().context(), endpoint, forward<CompletionToken>(token)).
template<class CompletionToken> DEDUCED async_accept(io_context& ctx, endpoint_type& endpoint, CompletionToken&& token);
Completion signature:
void(error_code ec, socket_type s).
Effects: Initiates an asynchronous operation to extract a socket from the queue of pending connections of the acceptor, as if by POSIX:
socklen_t endpoint_len = endpoint.capacity(); native_handle_type h = accept(native_handle(), endpoint.data(), &endpoint_len); if (h >= 0) endpoint.resize(endpoint_len);On success,
sissocket_type(ctx, h). Otherwise,sissocket_type(ctx)`.
void wait(wait_type w); void wait(wait_type w, error_code& ec);
Effects: Waits for the acceptor to have a queued incoming connection, or to have error conditions pending, as if by POSIX poll.
template<class CompletionToken> DEDUCED async_wait(wait_type w, CompletionToken&& token);
Completion signature:
void(error_code ec).
Effects: Initiates an asynchronous operation to wait for the acceptor to have a queued incoming connection, or to have error conditions pending, as if by POSIX poll.
When multiple asynchronous wait operations are initiated with the same
wait_typevalue, all outstanding operations complete when the acceptor enters the corresponding ready state. The order of invocation of the completions handlers for these operations is unspecified.
Error conditions:
—errc::bad_file_descriptor— ifis_open()isfalse.
          The class basic_socket_streambuf<Protocol, Clock, WaitTraits> associates both the input sequence
          and the output sequence with a socket. The input and output sequences do
          not support seeking. [Note: The input and output sequences
          are independent as a stream socket provides full duplex I/O. —end
          note]
        
[Note: This class is intended for sending and receiving bytes, not characters. The conversion from characters to bytes, and vice versa, must occur elsewhere. —end note]
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Protocol, class Clock, class WaitTraits> class basic_socket_streambuf : public basic_streambuf<char> { public: // types: typedef Protocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; typedef Clock clock_type; typedef typename clock_type::time_point time_point; typedef typename clock_type::duration duration; typedef WaitTraits traits_type; // construct / copy / destroy: basic_socket_streambuf(); explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s); basic_socket_streambuf(const basic_socket_streambuf&) = delete; basic_socket_streambuf(basic_socket_streambuf&& rhs); virtual ~basic_socket_streambuf(); basic_socket_streambuf& operator=(const basic_socket_streambuf&) = delete; basic_socket_streambuf& operator=(basic_socket_streambuf&& rhs); // members: basic_socket_streambuf* connect(const endpoint_type& e); template<class... Args> basic_socket_streambuf* connect(Args&&... ); basic_socket_streambuf<protocol_type>* close(); basic_socket<protocol_type>& socket(); error_code error() const; time_point expiry() const; void expires_at(const time_point& t); void expires_after(const duration& d); protected: // overridden virtual functions: virtual int_type underflow() override; virtual int_type pbackfail(int_type c = traits_type::eof()) override; virtual int_type overflow(int_type c = traits_type::eof()) override; virtual int sync() override; virtual streambuf* setbuf(char_type* s, streamsize n) override; private: basic_stream_socket<protocol_type> socket_; // exposition only error_code ec_; // exposition only time_point expiry_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_socket_streambuf
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), and MoveAssignable
          (C++Std [moveassignable]).
        
basic_socket_streambuf();
Effects: Initializes
socket_withctx, wherectxis an unspecified object of classio_context.
Postconditions:
expiry() == clock_type::max().
explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s);
Effects: Initializes
socket_withstd::move(s).
Postconditions:
expiry() == clock_type::max().
basic_socket_streambuf(basic_socket_streambuf&& rhs);
Effects: Move constructs from the rvalue
rhs. It is implementation-defined whether the sequence pointers in*this(eback(),gptr(),egptr(),pbase(),pptr(),epptr()) obtain the values whichrhshad. Whether they do or not,*thisandrhsreference separate buffers (if any at all) after the construction. Additionally*thisreferences the socket whichrhsdid before the construction, andrhsreferences no open socket after the construction.
Postconditions: Let
rhs_prefer to the state ofrhsjust prior to this construction and letrhs_arefer to the state ofrhsjust after this construction.
—is_open() == rhs_p.is_open()
—rhs_a.is_open() == false
—expiry() == rhs_p.expiry()
—rhs_a.expiry() == clock_type::max()
—gptr() - eback() == rhs_p.gptr() - rhs_p.eback()
—egptr() - eback() == rhs_p.egptr() - rhs_p.eback()
—ptr() - pbase() == rhs_p.pptr() - rhs_p.pbase()
—pptr() - pbase() == rhs_p.epptr() - rhs_p.pbase()
—if (eback()) eback() != rhs_a.eback()
—if (gptr()) gptr() != rhs_a.gptr()
—if (egptr()) egptr() != rhs_a.egptr()
—if (pbase()) pbase() != rhs_a.pbase()
—if (pptr()) pptr() != rhs_a.pptr()
—if (epptr()) epptr() != rhs_a.epptr()
virtual ~basic_socket_streambuf();
Effects: If a put area exists, calls
overflow(traits_type::eof())to flush characters. [Note: The socket is closed by thebasic_stream_socket<protocol_type>destructor. —end note]
basic_socket_streambuf& operator=(basic_socket_streambuf&& rhs);
Effects: Calls
this->close()then move assigns fromrhs. After the move assignment*thishas the observable state it would have had if it had been move constructed fromrhs.
Returns:
*this.
basic_socket_streambuf<protocol_type>* connect(const endpoint_type& e);
Effects: Initializes the
basic_socket_streambufas required, closes and re-opens the socket by performingsocket_.close(ec_)andsocket_.open(e.protocol(), ec_), then attempts to establish a connection as if by POSIXconnect(socket_.native_handle(), static_cast<sockaddr*>(e.data()), e.size()).ec_is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_, the socket is closed andec_is set toerrc::timed_out.
Returns: if
!ec_,this; otherwise, a null pointer.
template<class... Args> basic_socket_streambuf* connect(Args&&... args);
Effects: Initializes the
basic_socket_streambufas required and closes the socket as if by callingsocket_.close(ec_). Obtains an endpoint sequenceendpointsby performingprotocol_type::resolver(ctx).resolve(forward<Args>(args)...), wherectxis an unspecified object of classio_context. For each endpointein the sequence, closes and re-opens the socket by performingsocket_.close(ec_)andsocket_.open(e.protocol(), ec_), then attempts to establish a connection as if by POSIXconnect(socket_.native_handle(), static_cast<sockaddr*>(e.data()), e.size()).ec_is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_, the socket is closed andec_is set toerrc::timed_out.
Returns: if
!ec_,this; otherwise, a null pointer.
Remarks: This function shall not participate in overload resolution unless
Protocolmeets the requirements for an internet protocol.
basic_socket_streambuf* close();
Effects: If a put area exists, calls
overflow(traits_type::eof())to flush characters. Regardless of whether the preceding call fails or throws an exception, the function closes the socket as if bybasic_socket<protocol_type>::close(ec_). If any of the calls made by the function fail,closefails by returning a null pointer. If one of these calls throws an exception, the exception is caught and rethrown after closing the socket.
Returns:
thison success, a null pointer otherwise.
Postconditions:
is_open() == false.
basic_socket<protocol_type>& socket();
Returns:
socket_.
error_code error() const;
Returns:
ec_.
time_point expiry() const;
Returns:
expiry_.
void expires_at(const time_point& t);
Postconditions:
expiry_ == t.
void expires_after(const duration& d);
Effects: Equivalent to
expires_at(clock_type::now() + d).
virtual int_type underflow() override;
Effects: Behaves according to the description of
basic_streambuf<char>::underflow(), with the specialization that a sequence of characters is read from the input sequence as if by POSIX recvmsg, andec_is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_, the socket is closed andec_is set toerrc::timed_out.
Effects: Returns
traits_type::eof()to indicate failure. Otherwise returnstraits_type::to_int_type(*gptr()).
virtual int_type pbackfail(int_type c = traits_type::eof()) override;
Effects: Puts back the character designated by
cto the input sequence, if possible, in one of three ways:
— Iftraits_type::eq_int_type(c,traits_type::eof())returnsfalse, and if the function makes a putback position available, and iftraits_type::eq(traits_type::to_char_type(c),gptr()[-1])returnstrue, decrements the next pointer for the input sequence,gptr().
Returns:c.
— Iftraits_type::eq_int_type(c,traits_type::eof())returnsfalse, and if the function makes a putback position available, and if the function is permitted to assign to the putback position, decrements the next pointer for the input sequence, and storescthere.
Returns:c.
— Iftraits_type::eq_int_type(c,traits_type::eof())returnstrue, and if either the input sequence has a putback position available or the function makes a putback position available, decrements the next pointer for the input sequence,gptr().
Returns:traits_type::not_eof(c).
Returns:
traits_type::eof()to indicate failure.
Notes: The function does not put back a character directly to the input sequence. If the function can succeed in more than one of these ways, it is unspecified which way is chosen. The function can alter the number of putback positions available as a result of any call.
virtual int_type overflow(int_type c = traits_type::eof()) override;
Effects: Behaves according to the description of
basic_streambuf<char>::overflow(c), except that the behavior of "consuming characters" is performed by output of the characters to the socket as if by one or more calls to POSIX sendmsg, andec_is set to reflect the error code produced by the operation. If the operation does not complete before the absolute timeout specified byexpiry_, the socket is closed andec_is set toerrc::timed_out.
Returns:
traits_type::not_eof(c)to indicate success, andtraits_type::eof()to indicate failure.
virtual int sync() override;
Effects: If a put area exists, calls
overflow(traits_type::eof())to flush characters.
virtual streambuf* setbuf(char_type* s, streamsize n) override;
Effects: If
setbuf(nullptr, 0)is called on a stream before any I/O has occurred on that stream, the stream becomes unbuffered. Otherwise the results are unspecified. "Unbuffered" means thatpbase()andpptr()always return null and output to the socket should appear as soon as possible.
          The class template basic_socket_iostream<Protocol, Clock, WaitTraits> supports reading and writing on sockets.
          It uses a basic_socket_streambuf<Protocol, Clock, WaitTraits> object to control the associated sequences.
        
[Note: This class is intended for sending and receiving bytes, not characters. The conversion from characters to bytes, and vice versa, must occur elsewhere. —end note]
namespace std { namespace experimental { namespace net { inline namespace v1 { template<class Protocol, class Clock, class WaitTraits> class basic_socket_iostream : public basic_iostream<char> { public: // types: typedef Protocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; typedef Clock clock_type; typedef typename clock_type::time_point time_point; typedef typename clock_type::duration duration; typedef WaitTraits traits_type; // construct / copy / destroy: basic_socket_iostream(); explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s); basic_socket_iostream(const basic_socket_iostream&) = delete; basic_socket_iostream(basic_socket_iostream&& rhs); template<class... Args> explicit basic_socket_iostream(Args&&... args); basic_socket_iostream& operator=(const basic_socket_iostream&) = delete; basic_socket_iostream& operator=(basic_socket_iostream&& rhs); // members: template<class... Args> void connect(Args&&... args); void close(); basic_socket_streambuf<protocol_type, clock_type, traits_type>* rdbuf() const; basic_socket<protocol_type>& socket(); error_code error() const; time_point expiry() const; void expires_at(const time_point& t); void expires_after(const duration& d); private: basic_socket_streambuf<protocol_type, clock_type, traits_type> sb_; // exposition only }; } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of class template basic_socket_iostream
          meet the requirements of Destructible
          (C++Std [destructible]), MoveConstructible
          (C++Std [moveconstructible]), and MoveAssignable
          (C++Std [moveassignable]).
        
basic_socket_iostream();
Effects: Initializes the base class as
basic_iostream<char>(&sb_),sb_asbasic_socket_streambuf<Protocol, Clock, WaitTraits>(), and performssetf(std::ios_base::unitbuf).
explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s);
Effects: Initializes the base class as
basic_iostream<char>(&sb_),sb_asbasic_socket_streambuf<Protocol, Clock, WaitTraits>(std::move(s)), and performssetf(std::ios_base::unitbuf).
basic_socket_iostream(basic_socket_iostream&& rhs);
Effects: Move constructs from the rvalue
rhs. This is accomplished by move constructing the base class, and the containedbasic_socket_streambuf. Nextbasic_iostream<char>::set_rdbuf(&sb_)is called to install the containedbasic_socket_streambuf.
template<class... Args> explicit basic_socket_iostream(Args&&... args);
Effects: Initializes the base class as
basic_iostream<char>(&sb_), initializessb_asbasic_socket_streambuf<Protocol, Clock, WaitTraits>(), and performssetf(std::ios_base::unitbuf). Then callsrdbuf()->connect(forward<Args>(args)...). If that function returns a null pointer, callssetstate(failbit).
basic_socket_iostream& operator=(basic_socket_iostream&& rhs);
Effects: Move assigns the base and members of
*thisfrom the base and corresponding members ofrhs.
Returns:
*this.
template<class... Args> void connect(Args&&... args);
Effects: Calls
rdbuf()->connect(forward<Args>(args)...). If that function returns a null pointer, callssetstate(failbit)(which may throwios_base::failure).
void close();
Effects: Calls
rdbuf()->close(). If that function returns a null pointer, callssetstate(failbit)(which may throwios_base::failure).
basic_socket_streambuf<protocol_type, clock_type, traits_type>* rdbuf() const;
Returns:
const_cast<basic_socket_streambuf<protocol_type, clock_type, traits_type>*>(std::addressof(sb_)).
basic_socket<protocol_type>& socket();
Returns:
rdbuf()->socket().
error_code error() const;
Returns:
rdbuf()->error().
time_point expiry() const;
Returns:
rdbuf()->expiry().
void expires_at(const time_point& t);
Effects: Equivalent to
rdbuf()->expires_at(t).
void expires_after(const duration& d);
Effects: Equivalent to
rdbuf()->expires_after(d).
template<class Protocol, class EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints); template<class Protocol, class InputIterator> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, error_code& ec);
Returns:
connect(s, endpoints, [](auto, auto){ return true; }, ec).
template<class Protocol, class EndpointSequence, class ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, ConnectCondition c, error_code& ec);
Effects: Performs
ec.clear(), then finds the first elementepin the sequenceendpointsfor which:
—c(ec, ep)yieldstrue;
—s.close(ec)succeeds;
—s.open(ep.protocol(), ec)succeeds; and
—s.connect(ep, ec)succeeds.
Returns:
typename Protocol::endpoint()if no such element is found, otherwiseep.
Error conditions:
—socket_errc::not_found— ifendpoints.empty()or if the function objectcreturnedfalsefor all elements in the sequence.
template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last); template<class Protocol, class InputIterator> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, error_code& ec);
Returns:
connect(s, first, last, [](auto, auto){ return true; }, ec).
template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c); template<class Protocol, class InputIterator, class ConnectCondition> InputIterator connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, error_code& ec);
Effects: Performs
ec.clear(), then finds the first iteratoriin the range [first,last) for which:
—c(ec, *i)yieldstrue;
—s.close(ec)succeeds;
—s.open(typename Protocol::endpoint(*i).protocol(), ec)succeeds; and
—s.connect(*i, ec)succeeds.
Returns:
lastif no such iterator is found, otherwisei.
Error conditions:
—socket_errc::not_found— iffirst == lastor if the function objectcreturnedfalsefor all iterators in the range.
template<class Protocol, class EndpointSequence, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, CompletionToken&& token);
Returns:
async_connect(s, endpoints, [](auto, auto){ return true; }, forward<CompletionToken>(token)).
template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, const EndpointSequence& endpoints, ConnectCondition c, CompletionToken&& token);
Completion signature:
void(error_code ec, typename Protocol::endpoint ep).
Effects: Performs
ec.clear(), then finds the first elementepin the sequenceendpointsfor which:
—c(ec, ep)yieldstrue;
—s.close(ec)succeeds;
—s.open(ep.protocol(), ec)succeeds; and
— the asynchronous operations.async_connect(ep, unspecified)succeeds.
ecis updated with the result of thes.async_connect(ep, unspecified)operation, if any. If no such element is found, or if the operation fails with one of the error conditions listed below,epis set totypename Protocol::endpoint(). [Note: The underlyingclose,open, andasync_connectoperations are performed sequentially. —end note]
Error conditions:
—socket_errc::not_found— ifendpoints.empty()or if the function objectcreturnedfalsefor all elements in the sequence.
—errc::operation_canceled— ifs.is_open() == falseimmediately following anasync_connectoperation on the underlying socket.
template<class Protocol, class InputIterator, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, CompletionToken&& token);
Returns:
async_connect(s, first, last, [](auto, auto){ return true; }, forward<CompletionToken>(token)).
template<class Protocol, class InputIterator, class ConnectCondition, class CompletionToken> DEDUCED async_connect(basic_socket<Protocol>& s, InputIterator first, InputIterator last, ConnectCondition c, CompletionToken&& token);
Completion signature:
void(error_code ec, InputIterator i).
Effects: Performs
ec.clear(), then finds the first iteratoriin the range [first,last) for which:
—c(ec, *i)yieldstrue;
—s.close(ec)succeeds;
—s.open(typename Protocol::endpoint(*i).protocol(), ec)succeeds; and
— the asynchronous operations.async_connect(*i, unspecified)succeeds.
ecis updated with the result of thes.async_connect(*i, unspecified)operation, if any. If no such iterator is found, or if the operation fails with one of the error conditions listed below,iis set tolast. [Note: The underlyingclose,open, andasync_connectoperations are performed sequentially. —end note]
Error conditions:
—socket_errc::not_found— iffirst == lastor if the function objectcreturnedfalsefor all iterators in the range.
—errc::operation_canceled— ifs.is_open() == falseimmediately following anasync_connectoperation on the underlying socket.
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { enum class resolver_errc { host_not_found = implementation defined, // EAI_NONAME host_not_found_try_again = implementation defined, // EAI_AGAIN service_not_found = implementation defined // EAI_SERVICE }; const error_category& resolver_category() noexcept; error_code make_error_code(resolver_errc e) noexcept; error_condition make_error_condition(resolver_errc e) noexcept; typedef uint16_least_t port_type; typedef uint32_least_t scope_id_type; struct v4_mapped_t {}; constexpr v4_mapped_t v4_mapped; class address; class address_v4; class address_v6; class bad_address_cast; // address comparisons: constexpr bool operator==(const address&, const address&) noexcept; constexpr bool operator!=(const address&, const address&) noexcept; constexpr bool operator< (const address&, const address&) noexcept; constexpr bool operator> (const address&, const address&) noexcept; constexpr bool operator<=(const address&, const address&) noexcept; constexpr bool operator>=(const address&, const address&) noexcept; // address_v4 comparisons: constexpr bool operator==(const address_v4&, const address_v4&) noexcept; constexpr bool operator!=(const address_v4&, const address_v4&) noexcept; constexpr bool operator< (const address_v4&, const address_v4&) noexcept; constexpr bool operator> (const address_v4&, const address_v4&) noexcept; constexpr bool operator<=(const address_v4&, const address_v4&) noexcept; constexpr bool operator>=(const address_v4&, const address_v4&) noexcept; // address_v6 comparisons: constexpr bool operator==(const address_v6&, const address_v6&) noexcept; constexpr bool operator!=(const address_v6&, const address_v6&) noexcept; constexpr bool operator< (const address_v6&, const address_v6&) noexcept; constexpr bool operator> (const address_v6&, const address_v6&) noexcept; constexpr bool operator<=(const address_v6&, const address_v6&) noexcept; constexpr bool operator>=(const address_v6&, const address_v6&) noexcept; // address creation: address make_address(const char*); address make_address(const char*, error_code&) noexcept; address make_address(const string&); address make_address(const string&, error_code&) noexcept; address make_address(string_view); address make_address(string_view, error_code&) noexcept; // address_v4 creation: constexpr address_v4 make_address_v4(const address_v4::bytes_type&); constexpr address_v4 make_address_v4(address_v4::uint_type); constexpr address_v4 make_address_v4(v4_mapped_t, const address_v6&); address_v4 make_address_v4(const char*); address_v4 make_address_v4(const char*, error_code&) noexcept; address_v4 make_address_v4(const string&); address_v4 make_address_v4(const string&, error_code&) noexcept; address_v4 make_address_v4(string_view); address_v4 make_address_v4(string_view, error_code&) noexcept; // address_v6 creation: constexpr address_v6 make_address_v6(const address_v6::bytes_type&, scope_id_type = 0); constexpr address_v6 make_address_v6(v4_mapped_t, const address_v4&) noexcept; address_v6 make_address_v6(const char*); address_v6 make_address_v6(const char*, error_code&) noexcept; address_v6 make_address_v6(const string&); address_v6 make_address_v6(const string&, error_code&) noexcept; address_v6 make_address_v6(string_view); address_v6 make_address_v6(string_view, error_code&) noexcept; // address I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const address&); // address_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const address_v4&); // address_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const address_v6&); template<class> basic_address_iterator; // not defined template<> class basic_address_iterator<address_v4>; typedef basic_address_iterator<address_v4> address_v4_iterator; template<> class basic_address_iterator<address_v6>; typedef basic_address_iterator<address_v6> address_v6_iterator; template<class> basic_address_range; // not defined template<> class basic_address_range<address_v4>; typedef basic_address_range<address_v4> address_v4_range; template<> class basic_address_range<address_v6>; typedef basic_address_range<address_v6> address_v6_range; class network_v4; class network_v6; // network_v4 comparisons: bool operator==(const network_v4&, const network_v4&) noexcept; bool operator!=(const network_v4&, const network_v4&) noexcept; // network_v6 comparisons: bool operator==(const network_v6&, const network_v6&) noexcept; bool operator!=(const network_v6&, const network_v6&) noexcept; // network_v4 creation: network_v4 make_network_v4(const address_v4&, int); network_v4 make_network_v4(const address_v4&, const address_v4&); network_v4 make_network_v4(const char*); network_v4 make_network_v4(const char*, error_code&) noexcept; network_v4 make_network_v4(const string&); network_v4 make_network_v4(const string&, error_code&) noexcept; network_v4 make_network_v4(string_view); network_v4 make_network_v4(string_view, error_code&) noexcept; // network_v6 creation: network_v6 make_network_v6(const address_v6&, int); network_v6 make_network_v6(const char*); network_v6 make_network_v6(const char*, error_code&) noexcept; network_v6 make_network_v6(const string&); network_v6 make_network_v6(const string&, error_code&) noexcept; network_v6 make_network_v6(string_view); network_v6 make_network_v6(string_view, error_code&) noexcept; // network_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const network_v4&); // network_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const network_v6&); template<class InternetProtocol> class basic_endpoint; // basic_endpoint comparisons: template<class InternetProtocol> bool operator==(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator!=(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator< (const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator> (const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator<=(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> bool operator>=(const basic_endpoint<InternetProtocol>&, const basic_endpoint<InternetProtocol>&); // basic_endpoint I/O: template<class CharT, class Traits, class InternetProtocol> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>&, const basic_endpoint<InternetProtocol>&); template<class InternetProtocol> basic_resolver_entry; template<class InternetProtocol> bool operator==(const basic_resolver_entry<InternetProtocol>&, const basic_resolver_entry<InternetProtocol>&); template<class InternetProtocol> bool operator!=(const basic_resolver_entry<InternetProtocol>&, const basic_resolver_entry<InternetProtocol>&); template<class InternetProtocol> basic_resolver_results; template<class InternetProtocol> bool operator==(const basic_resolver_results<InternetProtocol>&, const basic_resolver_results<InternetProtocol>&); template<class InternetProtocol> bool operator!=(const basic_resolver_results<InternetProtocol>&, const basic_resolver_results<InternetProtocol>&); class resolver_base; template<class InternetProtocol> class basic_resolver; string host_name(); string host_name(error_code&); template<class Allocator> basic_string<char, char_traits<char>, Allocator> host_name(const Allocator&) const; template<class Allocator> basic_string<char, char_traits<char>, Allocator> host_name(const Allocator&, error_code&) const; class tcp; // tcp comparisons: bool operator==(const tcp& a, const tcp& b); bool operator!=(const tcp& a, const tcp& b); class udp; // udp comparisons: bool operator==(const udp& a, const udp& b); bool operator!=(const udp& a, const udp& b); class v6_only; namespace unicast { class hops; } // namespace unicast namespace multicast { class join_group; class leave_group; class outbound_interface; class hops; class enable_loopback; } // namespace multicast } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental template<> struct is_error_condition_enum< experimental::net::v1::ip::resolver_errc> : public true_type {}; // hash support template<class T> struct hash; template<> struct hash<experimental::net::v1::ip::address>; template<> struct hash<experimental::net::v1::ip::address_v4>; template<> struct hash<experimental::net::v1::ip::address_v6>; } // namespace std
            A type X meets the InternetProtocol requirements if it
            satisfies the requirements of AcceptableProtocol, as well
            as the additional requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            and b denotes a (possibly
            const) value of type X.
          
Table 33. InternetProtocol requirements
| expression | return type | 
                      assertion/note | 
|---|---|---|
| 
                       | 
                       | The type of a resolver for the protocol. | 
| 
                       | 
                       | Returns an object representing the IP version 4 protocol. | 
| 
                       | 
                       | Returns an object representing the IP version 6 protocol. | 
| 
                       | 
                      convertible to  | 
                      Returns  | 
| 
                       | 
                      convertible to  | 
                      Returns  | 
            A type X meets the MulticastGroupSocketOption requirements
            if it satisfies the requirements of Destructible
            (C++Std [destructible]), CopyConstructible
            (C++Std [copyconstructible]), CopyAssignable
            (C++Std [copyassignable]), and SettableSocketOption, as well
            as the additional requirements listed below.
          
            In the table below, a
            denotes a (possibly const) value of type X,
            b denotes a (possibly
            const) value of type address,
            c and d
            denote (possibly const) values of type address_v4,
            e denotes a (possibly
            const) value of type address_v6,
            f denotes a (possibly
            const) value of type unsigned
            int, and u
            denotes an identifier.
          
Table 34. MulticastGroupSocketOption requirements
| expression | type | 
                      assertion/note | 
|---|---|---|
| 
                       | Constructs a multicast group socket option to join the group with the specified version-independent address. | |
| 
                       | Constructs a multicast group socket option to join the specified IPv4 address on a specified network interface. | |
| 
                       | Constructs a multicast group socket option to join the specified IPv6 address on a specified network interface. | 
            In this Technical Specification, types that satisfy the MulticastGroupSocketOption requirements
            are defined as follows.
          
class C { public: // constructors: explicit C(const address& multicast_group) noexcept; explicit C(const address_v4& multicast_group, const address_v4& network_interface = address_v4::any()) noexcept; explicit C(const address_v6& multicast_group, unsigned int network_interface = 0) noexcept; };
Extensible implementations provide the following member functions:
class C { public: template<class Protocol> int level(const Protocol& p) const noexcept; template<class Protocol> int name(const Protocol& p) const noexcept; template<class Protocol> const void* data(const Protocol& p) const noexcept; template<class Protocol> size_t size(const Protocol& p) const noexcept; // remainder unchanged private: ip_mreq v4_value_; // exposition only ipv6_mreq v6_value_; // exposition only };
            Let L and N
            identify the POSIX macros to be passed as the level
            and option_name arguments, respectively, to POSIX
            setsockopt
            and getsockopt.
          
explicit C(const address& multicast_group) noexcept;
Effects: If
multicast_group.is_v6()istrue, callsC(multicast_group.to_v6()); otherwise, callsC(multicast_group.to_v4()).
explicit C(const address_v4& multicast_group, const address_v4& network_interface = address_v4::any()) noexcept;
Effects: For extensible implementations,
v4_value_.imr_multiaddris initialized to correspond to the addressmulticast_group,v4_value_.imr_interfaceis initialized to correspond to addressnetwork_interface, andv6_value_is zero-initialized.
explicit C(const address_v6& multicast_group, unsigned int network_interface = 0) noexcept;
Effects: For extensible implementations,
v6_value_.ipv6mr_multiaddris initialized to correspond to the addressmulticast_group,v6_value_.ipv6mr_interfaceis initialized tonetwork_interface, andv4_value_is zero-initialized.
template<class Protocol> int level(const Protocol& p) const noexcept;
Returns:
L.
template<class Protocol> int name(const Protocol& p) const noexcept;
Returns:
N.
template<class Protocol> const void* data(const Protocol& p) const noexcept;
Returns:
std::addressof(v6_value_)ifp.family() == AF_INET6, otherwisestd::addressof(v4_value_).
template<class Protocol> size_t size(const Protocol& p) const noexcept;
Returns:
sizeof(v6_value_)ifp.family() == AF_INET6, otherwisesizeof(v4_value_).
const error_category& resolver_category() noexcept;
Returns: A reference to an object of a type derived from class
error_category.
The object’s
default_error_conditionandequivalentvirtual functions behave as specified for the classerror_category. The object’snamevirtual function returns a pointer to the string"resolver".
error_code make_error_code(resolver_errc e) noexcept;
Returns:
error_code(static_cast<int>(e), resolver_category()).
error_condition make_error_condition(resolver_errc e) noexcept;
Returns:
error_condition(static_cast<int>(e), resolver_category()).
          The class address is a
          version-independent representation for an IP address. An object of class
          address holds either an
          IPv4 address, an IPv6 address, or no valid address.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class address { public: // constructors: constexpr address() noexcept; constexpr address(const address& a) noexcept; constexpr address(const address_v4& a) noexcept; constexpr address(const address_v6& a) noexcept; // assignment: address& operator=(const address& a) noexcept; address& operator=(const address_v4& a) noexcept; address& operator=(const address_v6& a) noexcept; // members: constexpr bool is_v4() const noexcept; constexpr bool is_v6() const noexcept; constexpr address_v4 to_v4() const; constexpr address_v6 to_v6() const; constexpr bool is_unspecified() const noexcept; constexpr bool is_loopback() const noexcept; constexpr bool is_multicast() const noexcept; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const; private: address_v4 v4_; // exposition only address_v6 v6_; // exposition only }; // address comparisons: constexpr bool operator==(const address& a, const address& b) noexcept; constexpr bool operator!=(const address& a, const address& b) noexcept; constexpr bool operator< (const address& a, const address& b) noexcept; constexpr bool operator> (const address& a, const address& b) noexcept; constexpr bool operator<=(const address& a, const address& b) noexcept; constexpr bool operator>=(const address& a, const address& b) noexcept; // address creation: address make_address(const char* str); address make_address(const char* str, error_code& ec) noexcept; address make_address(const string& str); address make_address(const string& str, error_code& ec) noexcept; address make_address(string_view str); address make_address(string_view str, error_code& ec) noexcept; // address I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address& addr); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          address satisfies the requirements
          for Destructible (C++Std
          [destructible]), CopyConstructible
          (C++Std [copyconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
constexpr address() noexcept;
Postconditions:
is_v4() == true,is_v6() == false, andis_unspecified() == true.
constexpr address(const address_v4& a) noexcept;
Effects: Initializes
v4_witha.
Postconditions:
is_v4() == trueandis_v6() == false.
constexpr address(const address_v6& a) noexcept;
Effects: Initializes
v6_witha.
Postconditions:
is_v4() == falseandis_v6() == true.
constexpr address(const address_v4& a) noexcept;
Postconditions:
is_v4() == trueandis_v6() == falseandto_v4() == a.
Returns:
*this
constexpr address(const address_v6& a) noexcept;
Postconditions:
is_v4() == falseandis_v6() == trueandto_v6() == a.
Returns:
*this
constexpr bool is_v4() const noexcept;
Returns:
trueif the object contains an IP version 4 address, otherwisefalse.
constexpr bool is_v6() const noexcept;
Returns:
trueif the object contains an IP version 6 address, otherwisefalse.
constexpr address_v4 to_v4() const;
Returns:
v4_.
Throws:
bad_address_castifis_v4() == false.
constexpr address_v6 to_v6() const;
Returns:
v6_.
Throws:
bad_address_castifis_v6() == false.
constexpr bool is_unspecified() const noexcept;
Returns: If
is_v4(), returnsv4_.is_unspecified(). Otherwise returnsv6_.is_unspecified().
constexpr bool is_loopback() const noexcept;
Returns: If
is_v4(), returnsv4_.is_loopback(). Otherwise returnsv6_.is_loopback().
constexpr bool is_multicast() const noexcept;
Returns: If
is_v4(), returnsv4_.is_multicast(). Otherwise returnsv6_.is_multicast().
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const;
Returns: If
is_v4(), returnsv4_.to_string(a). Otherwise returnsv6_.to_string(a).
[internet.address.comparisons]
constexpr bool operator==(const address& a, const address& b) noexcept;
Returns:
— ifa.is_v4() != b.is_v4(),false;
— ifa.is_v4(), the result ofa.v4_ == b.v4_;
— otherwise, the result ofa.v6_ == b.v6_.
constexpr bool operator!=(const address& a, const address& b) noexcept;
Returns:
!(a == b).
constexpr bool operator< (const address& a, const address& b) noexcept;
Returns:
— ifa.is_v4() && !b.is_v4(),true;
— if!a.is_v4() && b.is_v4(),false;
— ifa.is_v4(), the result ofa.v4_ < b.v4_;
— otherwise, the result ofa.v6_ < b.v6_.
constexpr bool operator> (const address& a, const address& b) noexcept;
Returns:
b < a.
constexpr bool operator<=(const address& a, const address& b) noexcept;
Returns:
!(b < a).
constexpr bool operator>=(const address& a, const address& b) noexcept;
Returns:
!(a < b).
address make_address(const char* str); address make_address(const char* str, error_code& ec) noexcept; address make_address(const string& str); address make_address(const string& str, error_code& ec) noexcept; address make_address(string_view str); address make_address(string_view str, error_code& ec) noexcept;
Effects: Converts a textual representation of an address into an object of class
address, as if by calling:address a; address_v6 v6a = make_address_v6(str, ec); if (!ec) a = v6a; else { address_v4 v4a = make_address_v4(str, ec); if (!ec) a = v4a; }
Returns:
a.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address& addr);
Returns:
os << addr.to_string().c_str().
          The class address_v4 is
          a representation of an IPv4 address.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class address_v4 { public: // types: typedef uint_least32_t uint_type; struct bytes_type; // constructors: constexpr address_v4() noexcept; constexpr address_v4(const address_v4& a) noexcept; constexpr address_v4(const bytes_type& bytes); explicit constexpr address_v4(uint_type val); // assignment: address_v4& operator=(const address_v4& a) noexcept; // members: constexpr bool is_unspecified() const noexcept; constexpr bool is_loopback() const noexcept; constexpr bool is_multicast() const noexcept; constexpr bytes_type to_bytes() const noexcept; constexpr uint_type to_uint() const noexcept; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const; // static members: static constexpr address_v4 any() noexcept; static constexpr address_v4 loopback() noexcept; static constexpr address_v4 broadcast() noexcept; }; // address_v4 comparisons: constexpr bool operator==(const address_v4& a, const address_v4& b) noexcept; constexpr bool operator!=(const address_v4& a, const address_v4& b) noexcept; constexpr bool operator< (const address_v4& a, const address_v4& b) noexcept; constexpr bool operator> (const address_v4& a, const address_v4& b) noexcept; constexpr bool operator<=(const address_v4& a, const address_v4& b) noexcept; constexpr bool operator>=(const address_v4& a, const address_v4& b) noexcept; // address_v4 creation: constexpr address_v4 make_address_v4(const address_v4::bytes_type& bytes); constexpr address_v4 make_address_v4(address_v4::uint_type val); constexpr address_v4 make_address_v4(v4_mapped_t, const address_v6& a); address_v4 make_address_v4(const char* str); address_v4 make_address_v4(const char* str, error_code& ec) noexcept; address_v4 make_address_v4(const string& str); address_v4 make_address_v4(const string& str, error_code& ec) noexcept; address_v4 make_address_v4(string_view str); address_v4 make_address_v4(string_view str, error_code& ec) noexcept; // address_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v4& addr); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          address_v4 satisfies the
          requirements for Destructible
          (C++Std [destructible]), CopyConstructible
          (C++Std [copyconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { struct address_v4::bytes_type : array<unsigned char, 4> { template<class... T> explicit constexpr bytes_type(T... t) : array<unsigned char, 4>{{static_cast<unsigned char>(t)...}} {} }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
            The ip::address_v4::bytes_type type is a standard-layout
            struct that provides a byte-level representation of an IPv4 address in
            network byte order.
          
constexpr address_v4() noexcept;
Postconditions:
to_bytes()yields{0, 0, 0, 0}andto_uint() == 0.
constexpr address_v4(const bytes_type& bytes);
Throws:
out_of_rangeif any element ofbytesis not in the range[0, 0xFF]. [Note: For implementations wherenumeric_limits<unsigned char>::max() == 0xFF, no out-of-range detection is needed. —end note]
Postconditions:
to_bytes() == bytesandto_uint() == (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3].
explicit constexpr address_v4(address_v4::uint_type val);
Throws:
out_of_rangeifvalis not in the range[0, 0xFFFFFFFF]. [Note: For implementations wherenumeric_limits<address_v4::uint_type>::max() == 0xFFFFFFFF, no out-of-range detection is needed. —end note]
Postconditions:
to_uint() == valandto_bytes()is{ (val >> 24) & 0xFF, (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF }.
constexpr bool is_unspecified() const noexcept;
Returns:
to_uint() == 0.
constexpr bool is_loopback() const noexcept;
Returns:
(to_uint() & 0xFF000000) == 0x7F000000.
constexpr bool is_multicast() const noexcept;
Returns:
(to_uint() & 0xF0000000) == 0xE0000000.
constexpr bytes_type to_bytes() const noexcept;
Returns: A representation of the address in network byte order.
constexpr address_v4::uint_type to_uint() const noexcept;
Returns: A representation of the address in host byte order.
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const;
Returns: If successful, the textual representation of the address, determined as if by POSIX inet_ntop when invoked with address family
AF_INET. Otherwisebasic_string<char, char_traits<char>, Allocator>(a).
static constexpr address_v4 any() noexcept;
Returns:
address_v4().
static constexpr address_v4 loopback() noexcept;
Returns:
address_v4(0x7F000001).
static constexpr address_v4 broadcast() noexcept;
Returns:
address_v4(0xFFFFFFFF).
[internet.address.v4.comparisons]
constexpr bool operator==(const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_uint() == b.to_uint().
constexpr bool operator!=(const address_v4& a, const address_v4& b) noexcept;
Returns:
!(a == b).
constexpr bool operator< (const address_v4& a, const address_v4& b) noexcept;
Returns:
a.to_uint() < b.to_uint().
constexpr bool operator> (const address_v4& a, const address_v4& b) noexcept;
Returns:
b < a.
constexpr bool operator<=(const address_v4& a, const address_v4& b) noexcept;
Returns:
!(b < a).
constexpr bool operator>=(const address_v4& a, const address_v4& b) noexcept;
Returns:
!(a < b).
[internet.address.v4.creation]
constexpr address_v4 make_address_v4(const address_v4::bytes_type& bytes);
Returns:
address_v4(bytes).
constexpr address_v4 make_address_v4(address_v4::uint_type val);
Returns:
address_v4(val).
constexpr address_v4 make_address_v4(v4_mapped_t, const address_v6& a);
Returns: An
address_v4object corresponding to the IPv4-mapped IPv6 address, as if computed by the following method:bytes_type v6b = a.to_bytes(); address_v4::bytes_type v4b(v6b[12], v6b[13], v6b[14], v6b[15]); return address_v4(v4b);
Throws:
bad_address_castifa.is_v4_mapped()isfalse.
address_v4 make_address_v4(const char* str); address_v4 make_address_v4(const char* str, error_code& ec) noexcept; address_v4 make_address_v4(const string& str); address_v4 make_address_v4(const string& str, error_code& ec) noexcept; address_v4 make_address_v4(string_view str); address_v4 make_address_v4(string_view str, error_code& ec) noexcept;
Effects: Converts a textual representation of an address into a corresponding
address_v4value, as if by POSIX inet_pton when invoked with address familyAF_INET.
Returns: If successful, an
address_v4value corresponding to the stringstr. Otherwiseaddress_v4().
Error conditions:
—errc::invalid_argument— ifstris not a valid textual representation of an IPv4 address.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v4& addr);
Returns:
os << addr.to_string().c_str().
          The class address_v6 is
          a representation of an IPv6 address.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class address_v6 { public: // types: struct bytes_type; // constructors: constexpr address_v6() noexcept; constexpr address_v6(const address_v6& a) noexcept; constexpr address_v6(const bytes_type& bytes, scope_id_type scope = 0); // assignment: address_v6& operator=(const address_v6& a) noexcept; // members: void scope_id(scope_id_type id) noexcept; constexpr scope_id_type scope_id() const noexcept; constexpr bool is_unspecified() const noexcept; constexpr bool is_loopback() const noexcept; constexpr bool is_multicast() const noexcept; constexpr bool is_link_local() const noexcept; constexpr bool is_site_local() const noexcept; constexpr bool is_v4_mapped() const noexcept; constexpr bool is_multicast_node_local() const noexcept; constexpr bool is_multicast_link_local() const noexcept; constexpr bool is_multicast_site_local() const noexcept; constexpr bool is_multicast_org_local() const noexcept; constexpr bool is_multicast_global() const noexcept; constexpr bytes_type to_bytes() const noexcept; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const; // static members: static constexpr address_v6 any() noexcept; static constexpr address_v6 loopback() noexcept; }; // address_v6 comparisons: constexpr bool operator==(const address_v6& a, const address_v6& b) noexcept; constexpr bool operator!=(const address_v6& a, const address_v6& b) noexcept; constexpr bool operator< (const address_v6& a, const address_v6& b) noexcept; constexpr bool operator> (const address_v6& a, const address_v6& b) noexcept; constexpr bool operator<=(const address_v6& a, const address_v6& b) noexcept; constexpr bool operator>=(const address_v6& a, const address_v6& b) noexcept; // address_v6 creation: constexpr address_v6 make_address_v6(const address_v6::bytes_type& bytes, scope_id_type scope_id = 0); constexpr address_v6 make_address_v6(v4_mapped_t, const address_v4& a) noexcept; address_v6 make_address_v6(const char* str); address_v6 make_address_v6(const char* str, error_code& ec) noexcept; address_v6 make_address_v6(const string& str); address_v6 make_address_v6(const string& str, error_code& ec) noexcept; address_v6 make_address_v6(string_view str); address_v6 make_address_v6(string_view str, error_code& ec) noexcept; // address_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v6& addr); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          address_v6 satisfies the
          requirements for Destructible
          (C++Std [destructible]), CopyConstructible
          (C++Std [copyconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
          [Note: The implementations of the functions is_unspecified, is_loopback,
          is_multicast, is_link_local, is_site_local,
          is_v4_mapped, is_multicast_node_local, is_multicast_link_local, is_multicast_site_local, is_multicast_org_local and is_multicast_global are determined by
          [RFC4291]. —end note]
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { struct address_v6::bytes_type : array<unsigned char, 16> { template<class... T> explicit constexpr bytes_type(T... t) : array<unsigned char, 16>{{static_cast<unsigned char>(t)...}} {} }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
            The ip::address_v6::bytes_type type is a standard-layout
            struct that provides a byte-level representation of an IPv6 address in
            network byte order.
          
constexpr address_v6() noexcept;
Postconditions:
is_unspecified() == trueandscope_id() == 0.
constexpr address_v6(const bytes_type& bytes, scope_id_type scope = 0);
Throws:
out_of_rangeif any element ofbytesis not in the range[0, 0xFF]. [Note: For implementations wherenumeric_limits<unsigned char>::max() == 0xFF, no out-of-range detection is needed. —end note]
Postconditions:
to_bytes() == bytesandscope_id() == scope.
void scope_id(scope_id_type id) noexcept;
Postconditions:
scope_id() == id.
constexpr scope_id_type scope_id() const noexcept;
Returns: The scope identifier associated with the address.
constexpr bool is_unspecified() const noexcept;
Returns:
*this == make_address_v6("::").
constexpr bool is_loopback() const noexcept;
Returns:
*this == make_address_v6("::1").
constexpr bool is_multicast() const noexcept;
Returns: A boolean indicating whether the
address_v6object represents a multicast address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFF;
constexpr bool is_link_local() const noexcept;
Returns: A boolean indicating whether the
address_v6object represents a unicast link-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFE && (b[1] & 0xC0) == 0x80;
constexpr bool is_site_local() const noexcept;
Returns: A boolean indicating whether the
address_v6object represents a unicast site-local address, as if computed by the following method:bytes_type b = to_bytes(); return b[0] == 0xFE && (b[1] & 0xC0) == 0xC0;
constexpr bool is_v4_mapped() const noexcept;
Returns: A boolean indicating whether the
address_v6object represents an IPv4-mapped IPv6 address, as if computed by the following method:bytes_type b = to_bytes(); return b[ 0] == 0 && b[ 1] == 0 && b[ 2] == 0 && b[ 3] == 0 && b[ 4] == 0 && b[ 5] == 0 && b[ 6] == 0 && b[ 7] == 0 && b[ 8] == 0 && b[ 9] == 0 && b[10] == 0xFF && b[11] == 0xFF;
constexpr bool is_multicast_node_local() const noexcept;
Returns:
is_multicast() && (to_bytes()[1] & 0x0F) == 0x01.
constexpr bool is_multicast_link_local() const noexcept;
Returns:
is_multicast() && (to_bytes()[1] & 0x0F) == 0x02.
constexpr bool is_multicast_site_local() const noexcept;
Returns:
is_multicast() && (to_bytes()[1] & 0x0F) == 0x05.
constexpr bool is_multicast_org_local() const noexcept;
Returns:
is_multicast() && (to_bytes()[1] & 0x0F) == 0x08.
constexpr bool is_multicast_global() const noexcept;
Returns:
is_multicast() && (to_bytes()[1] & 0x0F) == 0x0E.
constexpr bytes_type to_bytes() const noexcept;
Returns: A representation of the address in network byte order.
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const;
Effects: Converts an address into a textual representation. If
scope_id() == 0, converts as if by POSIX inet_ntop when invoked with address familyAF_INET6. Ifscope_id() != 0, the format isaddress%scope-id, whereaddressis the textual representation of the equivalent address havingscope_id() == 0, andscope-idis an implementation-defined textual representation of the scope identifier.
Returns: If successful, the textual representation of the address. Otherwise
basic_string<char, char_traits<char>, Allocator>(a).
static constexpr address_v6 any() noexcept;
Returns: An address
asuch that thea.is_unspecified() == trueanda.scope_id() == 0.
static constexpr address_v6 loopback() noexcept;
Returns: An address
asuch that thea.is_loopback() == trueanda.scope_id() == 0.
[internet.address.v6.comparisons]
constexpr bool operator==(const address_v6& a, const address_v6& b) noexcept;
Returns:
a.to_bytes() == b.to_bytes() && a.scope_id() == b.scope_id().
constexpr bool operator!=(const address_v6& a, const address_v6& b) noexcept;
Returns:
!(a == b).
constexpr bool operator< (const address_v6& a, const address_v6& b) noexcept;
Returns:
a.to_bytes() < b.to_bytes() || (!(b.to_bytes() < a.to_bytes()) && a.scope_id() < b.scope_id()).
constexpr bool operator> (const address_v6& a, const address_v6& b) noexcept;
Returns:
b < a.
constexpr bool operator<=(const address_v6& a, const address_v6& b) noexcept;
Returns:
!(b < a).
constexpr bool operator>=(const address_v6& a, const address_v6& b) noexcept;
Returns:
!(a < b).
[internet.address.v6.creation]
constexpr address_v6 make_address_v6(const address_v6::bytes_type& bytes, scope_id_type scope_id);
Returns:
address_v6(bytes, scope_id).
constexpr address_v6 make_address_v6(v4_mapped_t, const address_v4& a) noexcept;
Returns: An
address_v6object containing the IPv4-mapped IPv6 address corresponding to the specified IPv4 address, as if computed by the following method:address_v4::bytes_type v4b = a.to_bytes(); bytes_type v6b(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, v4b[0], v4b[1], v4b[2], v4b[3]); return address_v6(v6b);
address_v6 make_address_v6(const char* str); address_v6 make_address_v6(const char* str, error_code& ec) noexcept; address_v4 make_address_v6(const string& str); address_v4 make_address_v6(const string& str, error_code& ec) noexcept; address_v6 make_address_v6(string_view str); address_v6 make_address_v6(string_view str, error_code& ec) noexcept;
Effects: Converts a textual representation of an address into a corresponding
address_v6value. The format is eitheraddressoraddress%scope-id, whereaddressis in the format specified by POSIX inet_pton when invoked with address familyAF_INET6, andscope-idis an optional string specifying the scope identifier. All implementations accept asscope-ida textual representation of an unsigned decimal integer. It is implementation-defined whether alternative scope identifier representations are permitted. Ifscope-idis not supplied, anaddress_v6object is returned such thatscope_id() == 0.
Returns: If successful, an
address_v6value corresponding to the stringstr. Otherwise returnsaddress_v6().
Error conditions:
—errc::invalid_argument— ifstris not a valid textual representation of an IPv6 address.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const address_v6& addr);
Returns:
os << addr.to_string().c_str().
          An exception of type bad_address_cast
          is thrown by a failed address_cast.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class bad_address_cast : bad_cast { public: // constructor: bad_address_cast() noexcept; }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std bad_address_cast() noexcept;
Effects: constructs a
bad_address_castobject.
Postconditions:
what()returns an implementation-defined NTBS.
template<> struct hash<experimental::net::v1::ip::address>; template<> struct hash<experimental::net::v1::ip::address_v4>; template<> struct hash<experimental::net::v1::ip::address_v6>;
Requires: the template specializations shall meet the requirements of class template
hash(C++Std [unord.hash]).
          The class template basic_address_iterator
          enables iteration over IP addresses in network byte order. This clause
          defines two specializations of the class template basic_address_iterator:
          basic_address_iterator<address_v4> and basic_address_iterator<address_v6>. The members and operational semantics
          of these specializations are defined below.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<> class basic_address_iterator<Address> { public: // types: typedef Address value_type; typedef ptrdiff_t difference_type; typedef const Address* pointer; typedef const Address& reference; typedef input_iterator_tag iterator_category; // constructors: basic_address_iterator(const Address& a) noexcept; // members: reference operator*() const noexcept; pointer operator->() const noexcept; basic_address_iterator& operator++() noexcept; basic_address_iterator operator++(int) noexcept; basic_address_iterator& operator--() noexcept; basic_address_iterator operator--(int) noexcept; // other members as required by C++Std [input.iterators] private: Address address_; // exposition only }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Specializations of basic_address_iterator
          satisfy the requirements for input iterators (C++Std [input.iterators]).
        
basic_address_iterator(const Address& a) noexcept;
Effects: Initializes
address_witha.
reference operator*() const noexcept;
Returns:
address_.
pointer operator->() const noexcept;
Returns:
std::addressof(address_).
basic_address_iterator& operator++() noexcept;
Effects: Sets
address_to the next unique address in network byte order.
Returns:
*this.
basic_address_iterator operator++(int) noexcept;
Effects: Sets
address_to the next unique address in network byte order.
Returns: The prior value of
*this.
basic_address_iterator& operator--() noexcept;
Effects: Sets
address_to the prior unique address in network byte order.
Returns:
*this.
basic_address_iterator operator--(int) noexcept;
Effects: Sets
address_to the prior unique address in network byte order.
Returns: The prior value of
*this.
          The class template basic_address_range
          represents a range of IP addresses in network byte order. This clause defines
          two specializations of the class template basic_address_range:
          basic_address_range<address_v4>
          and basic_address_range<address_v6>. The members and operational semantics
          of these specializations are defined below.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<> class basic_address_range<Address> { public: // types: typedef basic_address_iterator<Address> iterator; // constructors: basic_address_range() noexcept; basic_address_range(const Address& first, const Address& last) noexcept; // members: iterator begin() const noexcept; iterator end() const noexcept; bool empty() const noexcept; size_t size() const noexcept; // not always defined iterator find(const Address& addr) const noexcept; }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Specializations of basic_address_range
          satisfy the requirements for Destructible
          (C++Std [destructible]), CopyConstructible
          (C++Std [copyconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
basic_address_range() noexcept;
Effects: Constructs an object of type
basic_address_range<Address>that represents an empty range.
basic_address_range(const Address& first, const Address& last) noexcept;
Effects: Constructs an object of type
basic_address_range<Address>that represents the half open range [first,last).
iterator begin() const noexcept;
Returns: An iterator that points to the beginning of the range.
iterator end() const noexcept;
Returns: An iterator that points to the end of the range.
bool empty() const noexcept;
Returns:
trueif*thisrepresents an empty range, otherwisefalse.
size_t size() const noexcept;
Returns: The number of unique addresses in the range.
Remarks: This member function is not defined when
Addressis typeaddress_v6.
iterator find(const Address& addr) const noexcept;
Returns: If
addris in the range, an iterator that points toaddr; otherwise,end().
Complexity: Constant time.
          The class network_v4 provides
          the ability to use and manipulate IPv4 network addresses.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class network_v4 { public: // constructors: constexpr network_v4() noexcept; constexpr network_v4(const address_v4& addr, int prefix_len); constexpr network_v4(const address_v4& addr, const address_v4& mask); // members: constexpr address_v4 address() const noexcept; constexpr int prefix_length() const noexcept; constexpr address_v4 netmask() const noexcept; constexpr address_v4 network() const noexcept; constexpr address_v4 broadcast() const noexcept; address_v4_range hosts() const noexcept; constexpr network_v4 canonical() const noexcept; constexpr bool is_host() const noexcept; constexpr bool is_subnet_of(const network_v4& other) const noexcept; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const; }; // network_v4 comparisons: constexpr bool operator==(const network_v4& a, const network_v4& b) noexcept; constexpr bool operator!=(const network_v4& a, const network_v4& b) noexcept; // network_v4 creation: constexpr network_v4 make_network_v4(const address_v4& addr, int prefix_len); constexpr network_v4 make_network_v4(const address_v4& addr, const address_v4& mask); network_v4 make_network_v4(const char* str); network_v4 make_network_v4(const char* str, error_code& ec) noexcept; network_v4 make_network_v4(const string& str); network_v4 make_network_v4(const string& str, error_code& ec) noexcept; network_v4 make_network_v4(string_view str); network_v4 make_network_v4(string_view str, error_code& ec) noexcept; // network_v4 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v4& addr); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          network_v4 satisfies the
          requirements for Destructible
          (C++Std [destructible]), CopyConstructible
          (C++Std [copyconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
constexpr network_v4() noexcept;
Postconditions:
this->address().is_unspecified() == trueandprefix_length() == 0.
constexpr network_v4(const address_v4& addr, int prefix_len);
Postconditions:
this->address() == addrandprefix_length() == prefix_len.
Throws:
out_of_rangeifprefix_len < 0' or 'prefix_len > 32.
constexpr network_v4(const address_v4& addr, const address_v4& mask);
Postconditions:
this->address() == addrandprefix_length()is equal to the number of contiguous non-zero bits.
Throws:
invalid_argumentifmaskcontains non-contiguous non-zero bits, or if the most significant bit is zero and any other bits are non-zero.
constexpr address_v4 address() const noexcept;
Returns: The address specified when the
network_v4object was constructed.
constexpr int prefix_length() const noexcept;
Returns: The prefix length of the network.
constexpr address_v4 netmask() const noexcept;
Returns: An
address_v4object withprefix_length()contiguous non-zero bits set, starting from the most significant bit in network byte order. All other bits are zero.
constexpr address_v4 network() const noexcept;
Returns: An
address_v4object with the firstprefix_length()bits, starting from the most significant bit in network byte order, set to the corresponding bit value ofthis->address(). All other bits are zero.
constexpr address_v4 broadcast() const noexcept;
Returns: An
address_v4object with the firstprefix_length()bits, starting from the most significant bit in network byte order, set to the corresponding bit value ofthis->address(). All other bits are non-zero.
address_v4_range hosts() const noexcept;
Returns: If
is_host() == true, anaddress_v4_rangeobject representing the single addressthis->address().Otherwise, anaddress_v4_rangeobject representing the range of unique host IP addresses in the network.
[Note: For IPv4, the network address and the broadcast address are not included in the range of host IP addresses. For example, given a network
192.168.1.0/24, the range returned byhosts()is from192.168.1.1to192.168.1.254inclusive, and neither192.168.1.0nor the broadcast address192.168.1.255are in the range. —end note]
constexpr network_v4 canonical() const noexcept;
Returns:
network_v4(network(), prefix_length()).
constexpr bool is_host() const noexcept;
Returns:
prefix_length() == 32.
constexpr bool is_subnet_of(const network_v4& other) const noexcept;
Returns:
trueifother.prefix_length() < prefix_length()andnetwork_v4(this->address(), other.prefix_length()).canonical() == other.canonical(), otherwisefalse.
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const;
Returns:
this->address().to_string(a) + "/" + to_string(prefix_length()).c_str().
[internet.network.v4.comparisons]
constexpr bool operator==(const network_v4& a, const network_v4& b) noexcept;
Returns:
trueifa.address() == b.address()anda.prefix_length() == b.prefix_length(), otherwisefalse.
constexpr bool operator!=(const network_v4& a, const network_v4& b) noexcept;
Returns:
!(a == b).
[internet.network.v4.creation]
constexpr network_v4 make_network_v4(const address_v4& addr, int prefix_len);
Returns:
network_v4(addr, prefix_len).
constexpr network_v4 make_network_v4(const address_v4& addr, const address_v4& mask);
Returns:
network_v4(addr, mask).
network_v4 make_network_v4(const char* str); network_v4 make_network_v4(const char* str, error_code& ec) noexcept; network_v4 make_network_v4(const string& str); network_v4 make_network_v4(const string& str, error_code& ec) noexcept; network_v4 make_network_v4(string_view str); network_v4 make_network_v4(string_view str, error_code& ec) noexcept;
Returns: If
strcontains a value of the form address'/'prefix-length, anetwork_v4object constructed with the result of applyingmake_address_v4()to the address portion of the string, and the result of converting prefix-length to an integer of typeint. Otherwise returnsnetwork_v4()and setsecto reflect the error.
Error conditions:
—errc::invalid_argument— ifstris not a valid textual representation of an IPv4 address and prefix length.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v4& net);
Returns:
os << net.to_string().c_str().
          The class network_v6 provides
          the ability to use and manipulate IPv6 network addresses.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class network_v6 { public: // constructors: constexpr network_v6() noexcept; constexpr network_v6(const address_v6& addr, int prefix_len); // members: constexpr address_v6 address() const noexcept; constexpr int prefix_length() const noexcept; constexpr address_v6 network() const noexcept; address_v6_range hosts() const noexcept; constexpr network_v6 canonical() const noexcept; constexpr bool is_host() const noexcept; constexpr bool is_subnet_of(const network_v6& other) const noexcept; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const; }; // network_v6 comparisons: constexpr bool operator==(const network_v6& a, const network_v6& b) noexcept; constexpr bool operator!=(const network_v6& a, const network_v6& b) noexcept; // network_v6 creation: constexpr network_v6 make_network_v6(const address_v6& addr, int prefix_len); network_v6 make_network_v6(const char* str); network_v6 make_network_v6(const char* str, error_code& ec) noexcept; network_v6 make_network_v6(const string& str); network_v6 make_network_v6(const string& str, error_code& ec) noexcept; network_v6 make_network_v6(const string_v6& str); network_v6 make_network_v6(const string_v6& str, error_code& ec) noexcept; // network_v6 I/O: template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v6& addr); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          network_v6 satisfies the
          requirements for Destructible
          (C++Std [destructible]), CopyConstructible
          (C++Std [copyconstructible]), and CopyAssignable
          (C++Std [copyassignable]).
        
constexpr network_v6() noexcept;
Postconditions:
this->address().is_unspecified() == trueandprefix_length() == 0.
constexpr network_v6(const address_v6& addr, int prefix_len);
Postconditions:
this->address() == addrandprefix_length() == prefix_len.
Throws:
out_of_rangeifprefix_len < 0orprefix_len > 128.
constexpr address_v6 address() const noexcept;
Returns: The address specified when the
network_v6object was constructed.
constexpr int prefix_length() const noexcept;
Returns: The prefix length of the network.
constexpr address_v6 network() const noexcept;
Returns: An
address_v6object with the firstprefix_length()bits, starting from the most significant bit in network byte order, set to the corresponding bit value ofthis->address(). All other bits are zero.
address_v6_range hosts() const noexcept;
Returns: If
is_host() == true, anaddress_v6_rangeobject representing the single addressthis->address().Otherwise, anaddress_v6_rangeobject representing the range of unique host IP addresses in the network.
constexpr network_v6 canonical() const noexcept;
Returns:
network_v6(network(), prefix_length()).
constexpr bool is_host() const noexcept;
Returns:
prefix_length() == 128.
constexpr bool is_subnet_of(const network_v6& other) const noexcept;
Returns:
trueifother.prefix_length() < prefix_length()andnetwork_v6(this->address(), other.prefix_length()).canonical() == other.canonical(), otherwisefalse.
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> to_string(const Allocator& a = Allocator()) const;
Returns:
this->address().to_string(a) + "/" + to_string(prefix_length()).c_str().
[internet.network.v6.comparisons]
constexpr bool operator==(const network_v6& a, const network_v6& b) noexcept;
Returns:
trueifa.address() == b.address()anda.prefix_length() == b.prefix_length(), otherwisefalse.
constexpr bool operator!=(const network_v6& a, const network_v6& b) noexcept;
Returns:
!(a == b).
[internet.network.v6.creation]
constexpr network_v6 make_network_v6(const address_v6& addr, int prefix_len);
Returns:
network_v6(addr, prefix_len).
network_v6 make_network_v6(const char* str); network_v6 make_network_v6(const char* str, error_code& ec) noexcept; network_v6 make_network_v6(const string& str); network_v6 make_network_v6(const string& str, error_code& ec) noexcept; network_v6 make_network_v6(const string_v6& str); network_v6 make_network_v6(const string_v6& str, error_code& ec) noexcept;
Returns: If
strcontains a value of the form address'/'prefix-length, anetwork_v6object constructed with the result of applyingmake_address_v6()to the address portion of the string, and the result of converting prefix-length to an integer of typeint. Otherwise returnsnetwork_v6()and setsecto reflect the error.
Error conditions:
—errc::invalid_argument— ifstris not a valid textual representation of an IPv6 address and prefix length.
template<class CharT, class Traits> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const network_v6& net);
Returns:
os << net.to_string().c_str().
          An object of type basic_endpoint<InternetProtocol> represents a protocol-specific endpoint,
          where an endpoint consists of an IP address and port number. Endpoints
          may be used to identify sources and destinations for socket connections
          and datagrams.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<class InternetProtocol> class basic_endpoint { public: // types: typedef InternetProtocol protocol_type; // constructors: constexpr basic_endpoint() noexcept; constexpr basic_endpoint(const protocol_type& proto, port_type port_num) noexcept; constexpr basic_endpoint(const ip::address& addr, port_type port_num) noexcept; // members: constexpr protocol_type protocol() const noexcept; constexpr ip::address address() const noexcept; void address(const ip::address& addr) noexcept; constexpr port_type port() const noexcept; void port(port_type port_num) noexcept; }; // basic_endpoint comparisons: template<class InternetProtocol> constexpr bool operator==(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept; template<class InternetProtocol> constexpr bool operator!=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept; template<class InternetProtocol> constexpr bool operator< (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept; template<class InternetProtocol> constexpr bool operator> (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept; template<class InternetProtocol> constexpr bool operator<=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept; template<class InternetProtocol> constexpr bool operator>=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept; // basic_endpoint I/O: template<class CharT, class Traits, class InternetProtocol> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const basic_endpoint<InternetProtocol>& ep); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          Instances of the basic_endpoint
          class template meet the requirements for an Endpoint.
        
Extensible implementations provide the following member functions:
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<class InternetProtocol> class basic_endpoint { public: void* data() noexcept; const void* data() const noexcept; constexpr size_t size() const noexcept; void resize(size_t s); constexpr size_t capacity() const noexcept; // remainder unchanged private: union { sockaddr_in v4_; sockaddr_in6 v6_; } data_; // exposition only }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
constexpr basic_endpoint() noexcept;
Postconditions:
this->address() == ip::address()andport() == 0.
constexpr basic_endpoint(const protocol_type& proto, port_type port_num) noexcept;
Requires:
proto == protocol_type::v4() || proto == protocol_type::v6().
Postconditions:
— Ifproto == protocol_type::v6(),this->address() == ip::address_v6(); otherwise,this->address() == ip::address_v4().
—port() == port_num.
constexpr basic_endpoint(const ip::address& addr, port_type port_num) noexcept;
Postconditions:
this->address() == addrandport() == port_num.
constexpr protocol_type protocol() const noexcept;
Returns:
protocol_type::v6()if the expressionthis->address().is_v6()istrue, otherwiseprotocol_type::v4().
constexpr ip::address address() const noexcept;
Returns: The address associated with the endpoint.
void address(const ip::address& addr) noexcept;
Postconditions:
this->address() == addr.
constexpr port_type port() const noexcept;
Returns: The port number associated with the endpoint.
void port(port_type port_num) noexcept;
Postconditions:
port() == port_num.
[internet.endpoint.comparisons]
template<class InternetProtocol> constexpr bool operator==(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept;
Returns:
a.address() == b.address() && a.port() == b.port()).
template<class InternetProtocol> constexpr bool operator!=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept;
Returns:
!(a == b).
template<class InternetProtocol> constexpr bool operator< (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept;
Returns:
a.address() < b.address() || (!(b.address() < a.address()) && a.port() < b.port()).
template<class InternetProtocol> constexpr bool operator> (const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept;
Returns:
b < a.
template<class InternetProtocol> constexpr bool operator<=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept;
Returns:
!(b < a).
template<class InternetProtocol> constexpr bool operator>=(const basic_endpoint<InternetProtocol>& a, const basic_endpoint<InternetProtocol>& b) noexcept;
Returns:
!(a < b).
template<class CharT, class Traits, class InternetProtocol> basic_ostream<CharT, Traits>& operator<<( basic_ostream<CharT, Traits>& os, const basic_endpoint<InternetProtocol>& ep);
Effects: Outputs a representation of the endpoint to the stream, as if it were implemented as follows:
basic_ostringstream<CharT, Traits> ss; if (ep.protocol() == protocol_type::v6()) ss << "[" << ep.address() << "]"; else ss << ep.address(); ss << ":" << ep.port(); os << ss.str();
Returns:
os.
[Note: The representation of the endpoint when it contains an IP version 6 address is based on [RFC2732]. —end note]
[internet.endpoint.extensible]
void* data() noexcept;
Returns:
std::addressof(data_).
const void* data() const noexcept;
Returns:
std::addressof(data_).
constexpr size_t size() const noexcept;
Returns:
sizeof(sockaddr_in6)ifprotocol().family() == AF_INET6, otherwisesizeof(sockaddr_in).
void resize(size_t s);
Throws:
length_errorif the conditionprotocol().family() == AF_INET6 && s != sizeof(sockaddr_in6)||protocol().family() == AF_INET4 && s != sizeof(sockaddr_in)istrue.
constexpr size_t capacity() const noexcept;
Returns:
sizeof(data_).
          An object of type basic_resolver_entry<InternetProtocol> represents a single element in the
          results returned by a name resolution operation.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<class InternetProtocol> class basic_resolver_entry { public: // types: typedef InternetProtocol protocol_type; typedef typename InternetProtocol::endpoint endpoint_type; // constructors: basic_resolver_entry(); basic_resolver_entry(const endpoint_type& ep, string_view h, string_view s); // members: endpoint_type endpoint() const; operator endpoint_type() const; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> host_name(const Allocator& a = Allocator()) const; template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> service_name(const Allocator& a = Allocator()) const; }; // basic_resolver_entry comparisons: template<class InternetProtocol> bool operator==(const basic_resolver_entry<InternetProtocol>& a, const basic_resolver_entry<InternetProtocol>& b); template<class InternetProtocol> bool operator!=(const basic_resolver_entry<InternetProtocol>& a, const basic_resolver_entry<InternetProtocol>& b); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
[internet.resolver.entry.cons]
basic_resolver_entry();
Effects: Equivalent to
basic_resolver_entry<InternetProtocol>(endpoint_type(), "", "").
basic_resolver_entry(const endpoint_type& ep, string_view h, string_view s);
Postconditions:
—endpoint() == ep.
—host_name() == h.
—service_name() == s.
[internet.resolver.entry.members]
endpoint_type endpoint() const;
Returns: The endpoint associated with the resolver entry.
operator endpoint_type() const;
Returns:
endpoint().
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> host_name(const Allocator& a = Allocator()) const;
Returns: The host name associated with the resolver entry.
Remarks: Ill-formed unless
allocator_traits<Allocator>::value_typeischar.
template<class Allocator = allocator<char>> basic_string<char, char_traits<char>, Allocator> service_name(const Allocator& a = Allocator()) const;
Returns: The service name associated with the resolver entry.
Remarks: Ill-formed unless
allocator_traits<Allocator>::value_typeischar.
[internet.resolver.entry.comparisons]
template<class InternetProtocol> bool operator==(const basic_resolver_entry<InternetProtocol>& a, const basic_resolver_entry<InternetProtocol>& b);
Returns:
a.endpoint() == b.endpoint() && a.host_name() == b.host_name() && a.service_name() == b.service_name().
template<class InternetProtocol> bool operator!=(const basic_resolver_entry<InternetProtocol>& a, const basic_resolver_entry<InternetProtocol>& b);
Returns:
!(a == b).
          An object of type basic_resolver_results<InternetProtocol> represents a sequence of basic_resolver_entry<InternetProtocol>
          elements resulting from a single name resolution operation.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<class InternetProtocol> class basic_resolver_results { public: // types: typedef InternetProtocol protocol_type; typedef typename protocol_type::endpoint endpoint_type; typedef basic_resolver_entry<protocol_type> value_type; typedef const value_type& const_reference; typedef value_type& reference; typedef implementation-defined const_iterator; typedef const_iterator iterator; typedef ptrdiff_t difference_type; typedef size_t size_type; // construct / copy / destroy: basic_resolver_results(); basic_resolver_results(const basic_resolver_results& rhs); basic_resolver_results(basic_resolver_results& rhs) noexcept; basic_resolver_results& operator=(const basic_resolver_results& rhs); basic_resolver_results& operator=(basic_resolver_results&& rhs); ~basic_resolver_results(); // size: size_type size() const noexcept; size_type max_size() const noexcept; bool empty() const noexcept; // element access: const_iterator begin() const; const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; // swap: void swap(basic_resolver_results& that) noexcept; }; // basic_resolver_results comparisons: template<class InternetProtocol> bool operator==(const basic_resolver_results<InternetProtocol>& a, const basic_resolver_results<InternetProtocol>& b); template<class InternetProtocol> bool operator!=(const basic_resolver_results<InternetProtocol>& a, const basic_resolver_results<InternetProtocol>& b); } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The class template basic_resolver_results
          satisfies the requirements of a sequence container (C++Std [sequence.reqmts]),
          except that only the operations defined for const-qualified sequence containers
          are supported. The class template basic_resolver_results
          supports forward iterators.
        
          A default-constructed basic_resolver_results
          object is empty. A non-empty results object is obtained only by calling
          a basic_resolver object's
          wait or async_wait
          operations, or otherwise by copy construction, move construction, assignment,
          or swap from another non-empty results object.
        
[internet.resolver.results.cons]
basic_resolver_results();
Postconditions:
size() == 0.
basic_resolver_results(const basic_resolver_results& rhs);
Postconditions:
*this == rhs.
basic_resolver_results(basic_resolver_results& rhs) noexcept;
Postconditions:
*thisis equal to the prior value ofrhs.
[internet.resolver.results.assign]
basic_resolver_results& operator=(const basic_resolver_results& rhs);
Postconditions:
*this == rhs.
Returns:
*this.
basic_resolver_results& operator=(basic_resolver_results& rhs) noexcept;
Postconditions:
*thisis equal to the prior value ofrhs.
Returns:
*this.
[internet.resolver.results.size]
size_type size() const noexcept;
Returns: The number of
basic_resolver_entryelements in*this.
size_type max_size() const noexcept;
Returns: The maximum number of
basic_resolver_entryelements that can be stored in*this.
bool empty() const noexcept;
Returns:
size() == 0.
[internet.resolver.results.access]
const_iterator begin() const; const_iterator cbegin() const;
Returns: A starting iterator that enumerates over all the
basic_resolver_entryelements stored in*this.
const_iterator end() const; const_iterator cend() const;
Returns: A terminating iterator that enumerates over all the
basic_resolver_entryelements stored in*this.
[internet.resolver.results.swap]
void swap(basic_resolver_results& that) noexcept;
Postconditions:
*thisis equal to the prior value ofthat, andthatis equal to the prior value of*this.
[internet.resolver.results.comparisons]
template<class InternetProtocol> bool operator==(const basic_resolver_results<InternetProtocol>& a, const basic_resolver_results<InternetProtocol>& b);
Returns:
a.size() == b.size() && equal(a.cbegin(), a.cend(), b.cbegin()).
template<class InternetProtocol> bool operator!=(const basic_resolver_results<InternetProtocol>& a, const basic_resolver_results<InternetProtocol>& b);
Returns:
!(a == b).
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class resolver_base { public: typedef T1 flags; static const flags passive; static const flags canonical_name; static const flags numeric_host; static const flags numeric_service; static const flags v4_mapped; static const flags all_matching; static const flags address_configured; protected: resolver_base(); ~resolver_base(); }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          resolver_base defines a
          bitmask type, flags, with
          the bitmask elements shown above.
        
Table 35. resolver flags
| Constant name | POSIX macro | Definition or notes | 
|---|---|---|
| 
                     | 
                     | Returned endpoints are intended for use as locally bound socket endpoints. | 
| 
                     | 
                     | Determine the canonical name of the host specified in the query. | 
| 
                     | 
                     | Host name should be treated as a numeric string defining an IPv4 or IPv6 address and no host name resolution should be attempted. | 
| 
                     | 
                     | Service name should be treated as a numeric string defining a port number and no service name resolution should be attempted. | 
| 
                     | 
                     | If the protocol is specified as an IPv6 protocol, return IPv4-mapped IPv6 addresses on finding no IPv6 addresses. | 
| 
                     | 
                     | 
                    If used with  | 
| 
                     | 
                     | Only return IPv4 addresses if a non-loopback IPv4 address is configured for the system. Only return IPv6 addresses if a non-loopback IPv6 address is configured for the system. | 
          Objects of type basic_resolver<InternetProtocol> are used to perform name resolution.
          Name resolution is the translation of a host name and service name into
          a sequence of endpoints, or the translation of an endpoint into its corresponding
          host name and service name.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { template<class InternetProtocol> class basic_resolver : public resolver_base { public: // types: typedef io_context::executor_type executor_type; typedef InternetProtocol protocol_type; typedef typename InternetProtocol::endpoint endpoint_type; typedef basic_resolver_results<InternetProtocol> results_type; // construct / copy / destroy: explicit basic_resolver(io_context& ctx); basic_resolver(const basic_resolver&) = delete; basic_resolver(basic_resolver&& rhs) noexcept; ~basic_resolver(); basic_resolver& operator=(const basic_resolver&) = delete; basic_resolver& operator=(basic_resolver&& rhs); // basic_resolver operations: executor_type get_executor() noexcept; void cancel(); results_type resolve(string_view host_name, string_view service_name); results_type resolve(string_view host_name, string_view service_name, error_code& ec); results_type resolve(string_view host_name, string_view service_name, flags f); results_type resolve(string_view host_name, string_view service_name, flags f, error_code& ec); template<class CompletionToken> DEDUCED async_resolve(string_view host_name, string_view service_name, CompletionToken&& token); template<class CompletionToken> DEDUCED async_resolve(string_view host_name, string_view service_name, flags f, CompletionToken&& token); results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name); results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name, error_code& ec); results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name, flags f); results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name, flags f, error_code& ec); template<class CompletionToken> DEDUCED async_resolve(const protocol_type& protocol, string_view host_name, string_view service_name, CompletionToken&& token); template<class CompletionToken> DEDUCED async_resolve(const protocol_type& protocol, string_view host_name, string_view service_name, flags f, CompletionToken&& token); results_type resolve(const endpoint_type& e); results_type resolve(const endpoint_type& e, error_code& ec); template<class CompletionToken> DEDUCED async_resolve(const endpoint_type& e, CompletionToken&& token); }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
explicit basic_resolver(io_context& ctx);
Postconditions:
get_executor() == ctx.get_executor().
basic_resolver(basic_resolver&& rhs) noexcept;
Effects: Move constructs an object of class
basic_resolver<InternetProtocol>that refers to the state originally represented byrhs.
Postconditions:
get_executor() == rhs.get_executor().
~basic_resolver();
Effects: Destroys the resolver, canceling all asynchronous operations associated with this resolver as if by calling
cancel().
basic_resolver& operator=(basic_resolver&& rhs);
Effects: Cancels all outstanding asynchronous operations associated with
*thisas if by callingcancel(), then moves into*thisthe state originally represented byrhs.
Postconditions:
get_executor() == ctx.get_executor().
Returns:
*this.
executor_type& get_executor() noexcept;
Returns: The associated executor.
void cancel();
Effects: Cancels all outstanding asynchronous resolve operations associated with
*this. Completion handlers for canceled operations are passed an error codeecsuch thatec == errc::operation_canceledyieldstrue.
results_type resolve(string_view host_name, string_view service_name); results_type resolve(string_view host_name, string_view service_name, error_code& ec);
Returns:
resolve(host_name, service_name, resolver_base::flags(), ec).
results_type resolve(string_view host_name, string_view service_name, flags f); results_type resolve(string_view host_name, string_view service_name, flags f, error_code& ec);
Effects: If
host_name.data() != nullptr, letHbe an NTBS constructed fromhost_name; otherwise, letHbenullptr. Ifservice_name.data() != nullptr, letSbe an NTBS constructed fromservice_name; otherwise, letSbenullptr. Resolves a host name and service name, as if by POSIX:addrinfo hints; hints.ai_flags = static_cast<int>(f); hints.ai_family = AF_UNSPEC; hints.ai_socktype = endpoint_type().protocol().type(); hints.ai_protocol = endpoint_type().protocol().protocol(); hints.ai_addr = nullptr; hints.ai_addrlen = 0; hints.ai_canonname = nullptr; hints.ai_next = nullptr; addrinfo* result = nullptr; getaddrinfo(H, S, &hints, &result);
Returns: On success, a non-empty results object containing the results of the resolve operation. Otherwise
results_type().
template<class CompletionToken> DEDUCED async_resolve(string_view host_name, string_view service_name, CompletionToken&& token);
Returns:
async_resolve(host_name, service_name, resolver_base::flags(), forward<CompletionToken>(token)).
template<class CompletionToken> DEDUCED async_resolve(string_view host_name, string_view service_name, flags f, CompletionToken&& token);
Completion signature:
void(error_code ec, results_type r).
Effects: If
host_name.data() != nullptr, letHbe an NTBS constructed fromhost_name; otherwise, letHbenullptr. Ifservice_name.data() != nullptr, letSbe an NTBS constructed fromservice_name; otherwise, letSbenullptr. Initiates an asynchronous operation to resolve a host name and service name, as if by POSIX:addrinfo hints; hints.ai_flags = static_cast<int>(f); hints.ai_family = AF_UNSPEC; hints.ai_socktype = endpoint_type().protocol().type(); hints.ai_protocol = endpoint_type().protocol().protocol(); hints.ai_addr = nullptr; hints.ai_addrlen = 0; hints.ai_canonname = nullptr; hints.ai_next = nullptr; addrinfo* result = nullptr; getaddrinfo(H, S, &hints, &result);On success,
ris a non-empty results object containing the results of the resolve opeation. Otherwise,risresults_type().
results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name); results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name, error_code& ec);
Returns:
resolve(protocol, host_name, service_name, resolver_base::flags(), ec).
results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name, flags f); results_type resolve(const protocol_type& protocol, string_view host_name, string_view service_name, flags f, error_code& ec);
Effects: If
host_name.data() != nullptr, letHbe an NTBS constructed fromhost_name; otherwise, letHbenullptr. Ifservice_name.data() != nullptr, letSbe an NTBS constructed fromservice_name; otherwise, letSbenullptr. Resolves a host name and service name, as if by POSIX:addrinfo hints; hints.ai_flags = static_cast<int>(f); hints.ai_family = protocol.family(); hints.ai_socktype = protocol.type(); hints.ai_protocol = protocol.protocol(); hints.ai_addr = nullptr; hints.ai_addrlen = 0; hints.ai_canonname = nullptr; hints.ai_next = nullptr; addrinfo* result = nullptr; getaddrinfo(H, S, &hints, &result);
Returns: On success, a non-empty results object containing the results of the resolve operation. Otherwise
results_type().
template<class CompletionToken> DEDUCED async_resolve(const protocol_type& protocol, string_view host_name, string_view service_name, CompletionToken&& token);
Returns:
async_resolve(protocol, host_name, service_name, resolver_base::flags(), forward<CompletionToken>(token)).
template<class CompletionToken> DEDUCED async_resolve(const protocol& protocol, string_view host_name, string_view service_name, flags f, CompletionToken&& token);
Completion signature:
void(error_code ec, results_type r).
Effects: If
host_name.data() != nullptr, letHbe an NTBS constructed fromhost_name; otherwise, letHbenullptr. Ifservice_name.data() != nullptr, letSbe an NTBS constructed fromservice_name; otherwise, letSbenullptr. Initiates an asynchronous operation to resolve a host name and service name, as if by POSIX:addrinfo hints; hints.ai_flags = static_cast<int>(f); hints.ai_family = protocol.family(); hints.ai_socktype = protocol.type(); hints.ai_protocol = protocol.protocol(); hints.ai_addr = nullptr; hints.ai_addrlen = 0; hints.ai_canonname = nullptr; hints.ai_next = nullptr; addrinfo* result = nullptr; getaddrinfo(H, S, &hints, &result);On success,
ris a non-empty results object containing the results of the resolve opeation. Otherwise,risresults_type().
results_type resolve(const endpoint_type& e); results_type resolve(const endpoint_type& e, error_code& ec);
Effects: Let
S1andS2be implementation-defined values that are sufficiently large to hold the host name and service name respectively. Resolves an endpoint as if by POSIX:char host_name[S1]; char service_name[S2]; int flags = 0; if (endpoint_type().protocol().type() == SOCK_DGRAM) flags |= NI_DGRAM; int result = getnameinfo(e.data(), e.size(), host_name, S1, service_name, S2, flags); if (result != 0) { flags |= NI_NUMERICSERV; result = getnameinfo(e.data(), e.size(), host_name, S1, service_name, S2, flags); }
Returns: On success, a results object with
size() == 1containing the results of the resolve operation. Otherwiseresults_type().
template<class CompletionToken> DEDUCED async_resolve(const endpoint_type& e, CompletionToken&& token);
Completion signature:
void(error_code ec, results_type r).
Effects: Let
S1andS2be implementation-defined values that are sufficiently large to hold the host name and service name respectively. Initiates an asynchronous operation to resolve an endpoint as if by POSIX:char host_name[S1]; char service_name[S2]; int flags = 0; if (endpoint_type().protocol().type() == SOCK_DGRAM) flags |= NI_DGRAM; int result = getnameinfo(e.data(), e.size(), host_name, S1, service_name, S2, flags); if (result != 0) { flags |= NI_NUMERICSERV; result = getnameinfo(e.data(), e.size(), host_name, S1, service_name, S2, flags); }On success,
ris a results object withsize() == 1containing the results of the resolve operation; otherwise,risresults_type().
string host_name(); string host_name(error_code& ec); template<class Allocator> basic_string<char, char_traits<char>, Allocator> host_name(const Allocator& a) const; template<class Allocator> basic_string<char, char_traits<char>, Allocator> host_name(const Allocator& a, error_code& ec) const;
Returns: The standard host name for the current machine, determined as if by POSIX gethostname.
Remarks: In the last two overloads, ill-formed unless
allocator_traits<Allocator>::value_typeischar.
          The class tcp encapsulates
          the types and flags necessary for TCP sockets.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class tcp { public: // types: typedef basic_endpoint<tcp> endpoint; typedef basic_resolver<tcp> resolver; typedef basic_stream_socket<tcp> socket; typedef basic_socket_acceptor<tcp> acceptor; typedef basic_socket_iostream<tcp> iostream; class no_delay; // static members: static constexpr tcp v4() noexcept; static constexpr tcp v6() noexcept; tcp() = delete; }; // tcp comparisons: constexpr bool operator==(const tcp& a, const tcp& b) noexcept; constexpr bool operator!=(const tcp& a, const tcp& b) noexcept; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The tcp class meets the
          requirements for an InternetProtocol.
        
Extensible implementations provide the following member functions:
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class tcp { public: constexpr int family() const noexcept; constexpr int type() const noexcept; constexpr int protocol() const noexcept; // remainder unchanged }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
The return values for these member functions are listed in the table below.
Table 36. Behavior of extensible implementations
| value | 
                     | 
                     | 
                     | 
|---|---|---|---|
| 
                     | 
                     | 
                     | 
                     | 
| 
                     | 
                     | 
                     | 
                     | 
          [Note: The constants AF_INET,
          AF_INET6 and SOCK_STREAM are defined in the POSIX
          header file sys/socket.h. The constant IPPROTO_TCP is defined in the POSIX header
          file netinet/in.h.
          —end note]
        
constexpr bool operator==(const tcp& a, const tcp& b) noexcept;
Returns: A boolean indicating whether two objects of class
tcpare equal, such that the expressiontcp::v4() == tcp::v4()istrue, the expressiontcp::v6() == tcp::v6()istrue, and the expressiontcp::v4() == tcp::v6()isfalse.
constexpr bool operator!=(const tcp& a, const tcp& b) noexcept;
Returns:
!(a == b).
          The class udp encapsulates
          the types and flags necessary for UDP sockets.
        
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class udp { public: // types: typedef basic_endpoint<udp> endpoint; typedef basic_resolver<udp> resolver; typedef basic_datagram_socket<udp> socket; // static members: static constexpr udp v4() noexcept; static constexpr udp v6() noexcept; udp() = delete; }; // udp comparisons: constexpr bool operator==(const udp& a, const udp& b) noexcept; constexpr bool operator!=(const udp& a, const udp& b) noexcept; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
          The udp class meets the
          requirements for an InternetProtocol.
        
Extensible implementations provide the following member functions:
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { class udp { public: constexpr int family() const noexcept; constpexr int type() const noexcept; constexpr int protocol() const noexcept; // remainder unchanged }; } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
The return values for these member functions are listed in the table below.
Table 37. Behavior of extensible implementations
| value | 
                     | 
                     | 
                     | 
|---|---|---|---|
| 
                     | 
                     | 
                     | 
                     | 
| 
                     | 
                     | 
                     | 
                     | 
          [Note: The constants AF_INET,
          AF_INET6 and SOCK_DGRAM are defined in the POSIX header
          file sys/socket.h. The constant IPPROTO_UDP is defined in the POSIX header
          file netinet/in.h.
          —end note]
        
constexpr bool operator==(const udp& a, const udp& b) noexcept;
Returns: A boolean indicating whether two objects of class
udpare equal, such that the expressionudp::v4() == udp::v4()istrue, the expressionudp::v6() == udp::v6()istrue, and the expressionudp::v4() == udp::v6()isfalse.
constexpr bool operator!=(const udp& a, const udp& b) noexcept;
Returns:
!(a == b).
          In the table below, let C denote
          a socket option class; let L identify
          the POSIX macro to be passed as the level argument
          to POSIX setsockopt
          and getsockopt;
          let N identify the POSIX macro
          to be passed as the option_name argument to POSIX
          setsockopt
          and getsockopt;
          let T identify the type of the
          value whose address will be passed as the option_value
          argument to POSIX setsockopt
          and getsockopt;
          let p denote a (possibly
          const) value of a type meeting the protocol
          requirements, as passed to the socket option's level
          and name member functions;
          and let F be the value of p.family().
        
Table 38. Internet socket options
| C | L | N | T | Requirements, definition or notes | 
|---|---|---|---|---|
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | Specifies the network interface to use for outgoing multicast datagrams. | |
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
| 
                     | 
                     | 
                     | 
                     | 
                    Satisfies the  | 
            The outbound_interface
            class represents a socket option that specifies the network interface
            to use for outgoing multicast datagrams.
          
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { namespace multicast { class outbound_interface { public: // constructors: explicit outbound_interface(const address_v4& network_interface) noexcept; explicit outbound_interface(unsigned int network_interface) noexcept; }; } // namespace multicast } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
            outbound_interface satisfies
            the requirements for Destructible
            (C++Std [destructible]), CopyConstructible
            (C++Std [copyconstructible]), CopyAssignable
            (C++Std [copyassignable]), and SettableSocketOption.
          
Extensible implementations provide the following member functions:
namespace std { namespace experimental { namespace net { inline namespace v1 { namespace ip { namespace multicast { class outbound_interface { public: template<class Protocol> int level(const Protocol& p) const noexcept; template<class Protocol> int name(const Protocol& p) const noexcept; template<class Protocol> const void* data(const Protocol& p) const noexcept; template<class Protocol> size_t size(const Protocol& p) const noexcept; // remainder unchanged private: in_addr v4_value_; // exposition only unsigned int v6_value_; // exposition only }; } // namespace multicast } // namespace ip } // inline namespace v1 } // namespace net } // namespace experimental } // namespace std
explicit outbound_interface(const address_v4& network_interface) noexcept;
Effects: For extensible implementations,
v4_value_is initialized to correspond to the IPv4 addressnetwork_interface, andv6_value_is zero-initialized.
explicit outbound_interface(unsigned int network_interface) noexcept;
Effects: For extensible implementations,
v6_value_is initialized tonetwork_interface, andv4_value_is zero-initialized.
template<class Protocol> int level(const Protocol& p) const noexcept;
Returns:
IPPROTO_IPV6ifp.family() == AF_INET6, otherwiseIPPROTO_IP.
template<class Protocol> int name(const Protocol& p) const noexcept;
Returns:
IPV6_MULTICAST_HOPSifp.family() == AF_INET6, otherwiseIP_MULTICAST_HOPS.
template<class Protocol> const void* data(const Protocol& p) const noexcept;
Returns:
std::addressof(v6_value_)ifp.family() == AF_INET6, otherwisestd::addressof(v4_value_).
template<class Protocol> size_t size(const Protocol& p) const noexcept;
Returns:
sizeof(v6_value_)ifp.family() == AF_INET6, otherwisesizeof(v4_value_).
In the eleven years since Asio's inception, hundreds of people have contributed to its development through design review, patches, feature suggestions, bug reports, and usage feedback from the field. With respect to the 2014 refresh of the Networking Library Proposal, the author would particularly like to thank Jamie Allsop for providing feedback during the drafting process, and Oliver Kowalke for contributing towards the design and implementation of the CIDR support.
The author would also like to thank Marshall Clow, Jens Maurer, Arash Partow, Jamie Allsop, Dietmar Kühl, Detlef Vollmann, Jonathan Wakely, Mikael Kilpeläinen, Jens Weller, Michael Wong, Eric Fisselier, and Jeffrey Yasskin for participating in the Cologne LWG wording review of the Networking Library TS proposal, which contributed significantly to the changes in this revision.
[POSIX] ISO/IEC 9945:2003, IEEE Std 1003.1-2001, and The Open Group Base Specifications, Issue 6. Also known as The Single Unix Specification, Version 3.
[N4045] Kohlhoff, Christopher, Library Foundations for Asynchronous Operations, Revision 2, 2014.
[P0113] Kohlhoff, Christopher, Executors and Asynchronous Operations, Revision 2, 2015.
[N4099] Draft Filesystem Technical Specification, 2014.
[ACE] Schmidt, Douglas C., ADAPTIVE Communication Environment, http://www.cs.wustl.edu/~schmidt/ACE.html.
[SYMBIAN] Symbian Ltd, Sockets Client, http://www.symbian.com/developer/techlib/v70sdocs/doc_source/reference/cpp/SocketsClient/index.html.
[MS-NET] Microsoft Corporation, .NET Framework Class Library, Socket Class, http://msdn2.microsoft.com/en-us/library/system.net.sockets.socket.aspx.
[ES-API] The Interconnect Software Consortium / The Open Group, Extended Sockets API (ES-API), Issue 1.0, 2005, http://opengroup.org/icsc/uploads/40/6415/ES_API_1_0.pdf.
[UNPV1] Stevens, W. Richard, UNIX Network Programming, Volume 1, 2nd Edition, Prentice Hall, 1998.
[POSA2] Schmidt, Douglas C. et al, Pattern Oriented Software Architecture, Volume 2, Wiley, 2000.
[RFC821] Postel, J., RFC 821: Simple Mail Transfer Protocol, 1982, http://www.ietf.org/rfc/rfc0821.txt.
[RFC959] Postel, J. and Reynolds, J., RFC 959: File Transfer Protocol (FTP), 1985, http://www.ietf.org/rfc/rfc0959.txt.
[RFC2616] Fielding, R. et al, RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1, 1999, http://www.ietf.org/rfc/rfc2616.txt.
[RFC2732] Hinden, R., Carpenter, B. and Masinter, L., RFC 2732: Format for Literal IPv6 Addresses in URL's, 1999, http://www.ietf.org/rfc/rfc2732.txt.
[RFC3513] Hinden, R. and Deering, S., RFC 3513: Internet Protocol Version 6 (IPv6) Addressing Architecture, 2003, http://www.ietf.org/rfc/rfc3513.txt.
[1] POSIX® is a registered trademark of The IEEE. Windows® is a registered trademark of Microsoft Corporation. This information is given for the convenience of users of this document and does not constitute an endorsement by ISO or IEC of these products.