public inbox for libstdc++-cvs@sourceware.org help / color / mirror / Atom feed
From: Alexandre Oliva <aoliva@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/users/aoliva/heads/testme)] libstdc++: Better requirements checking in Networking TS Date: Tue, 26 May 2020 04:37:02 +0000 (GMT) [thread overview] Message-ID: <20200526043702.8C62D395CC54@sourceware.org> (raw) https://gcc.gnu.org/g:b780db2ea327f51050d64237e71456b0eacf60e8 commit b780db2ea327f51050d64237e71456b0eacf60e8 Author: Jonathan Wakely <jwakely@redhat.com> Date: Thu May 21 00:59:55 2020 +0100 libstdc++: Better requirements checking in Networking TS Define concepts and traits for checking type requirements. * include/experimental/bits/net.h (__endpoint, __protocol) (__acceptable_protocol, __inet_protocol): New concepts. (__detail::__is_endpoint): Move trait from <experimental/socket>. (__is_protocol, __is_acceptable_protocol, __is_inet_protocol): New traits. (__endpoint, __protocol, __acceptable_protocol): New variable templates. * include/experimental/socket (__is_endpoint): Move to net.h header. (basic_socket, basic_socket_acceptor): Check requirements. Diff: --- libstdc++-v3/ChangeLog | 10 ++ libstdc++-v3/include/experimental/bits/net.h | 152 +++++++++++++++++++++++++++ libstdc++-v3/include/experimental/socket | 34 ++---- 3 files changed, 169 insertions(+), 27 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index dec84f03da6..975de44434b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,15 @@ 2020-05-21 Jonathan Wakely <jwakely@redhat.com> + * include/experimental/bits/net.h (__endpoint, __protocol) + (__acceptable_protocol, __inet_protocol): New concepts. + (__detail::__is_endpoint): Move trait from <experimental/socket>. + (__is_protocol, __is_acceptable_protocol, __is_inet_protocol): New + traits. + (__endpoint, __protocol, __acceptable_protocol): New variable + templates. + * include/experimental/socket (__is_endpoint): Move to net.h header. + (basic_socket, basic_socket_acceptor): Check requirements. + * include/experimental/executor (use_future_t::use_future_t()): Fix incorrect noexcept-specifier. * include/experimental/internet (basic_resolver_results): Adjust diff --git a/libstdc++-v3/include/experimental/bits/net.h b/libstdc++-v3/include/experimental/bits/net.h index f69ef91c31e..cf7914d0acb 100644 --- a/libstdc++-v3/include/experimental/bits/net.h +++ b/libstdc++-v3/include/experimental/bits/net.h @@ -38,6 +38,10 @@ #include <system_error> #include <experimental/netfwd> +#if __cplusplus > 201703L +# include <concepts> +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -164,6 +168,154 @@ inline namespace v1 { return _Derived::_S_name; } }; +namespace __detail +{ +#if __cpp_lib_concepts + template<typename _Tp> + concept __protocol_like + = copyable<_Tp> && requires { typename _Tp::endpoint; }; + + // Endpoint requirements for non-extensible implementations. + template<typename _Tp> + concept __endpoint_base = semiregular<_Tp> + && requires { typename _Tp::protocol_type; } + && __protocol_like<typename _Tp::protocol_type> + && requires(const _Tp __a) { + { __a.protocol() } -> same_as<typename _Tp::protocol_type>; + }; + + // Endpoint requirements for extensible implementations. + template<typename _Tp> + concept __endpoint = __endpoint_base<_Tp> + && requires (const _Tp& __a, _Tp& __b, size_t __s) + { + { __a.data() } -> same_as<const void*>; + { __b.data() } -> same_as<void*>; + { __b.size() } -> same_as<size_t>; + __b.resize(__s); + { __a.capacity() } -> same_as<size_t>; + }; + + // Protocol requirements for non-extensible implementations. + template<typename _Tp> + concept __protocol_base = __protocol_like<_Tp> + && __endpoint_base<typename _Tp::endpoint> + && same_as<typename _Tp::endpoint::protocol_type, _Tp>; + + // Protocol requirements for extensible implementations. + template<typename _Tp> + concept __protocol = __protocol_base<_Tp> + && __endpoint<typename _Tp::endpoint> + && requires (const _Tp __a) { + { __a.family() } -> same_as<int>; + { __a.type() } -> same_as<int>; + { __a.protocol() } -> same_as<int>; + }; + + template<typename _Tp> + concept __acceptable_protocol = __protocol<_Tp> + && requires { typename _Tp::socket; } + && move_constructible<typename _Tp::socket> + && derived_from<typename _Tp::socket, basic_socket<_Tp>>; + + template<typename _Tp> + concept __inet_protocol = __acceptable_protocol<_Tp> + && equality_comparable<_Tp> && requires { + { _Tp::v4() } -> same_as<_Tp>; + { _Tp::v6() } -> same_as<_Tp>; + typename _Tp::resolver; + } + && same_as<typename _Tp::resolver, ip::basic_resolver<_Tp>>; + +#else + // Check Endpoint requirements for extensible implementations + template<typename _Tp, typename = void> + struct __is_endpoint : false_type + { }; + + template<typename _Tp> + auto + __endpoint_reqs(const _Tp* __a = nullptr, _Tp* __b = nullptr) + -> enable_if_t<__and_< + is_default_constructible<_Tp>, __is_value_constructible<_Tp>, + is_same<decltype(__a->protocol()), typename _Tp::protocol_type>, + is_same<decltype(__a->data()), const void*>, + is_same<decltype(__b->data()), void*>, + is_same<decltype(__a->size()), size_t>, + is_same<decltype(__a->capacity()), size_t> + >::value, + __void_t< typename _Tp::protocol_type::endpoint, + decltype(__b->resize(std::declval<size_t>())) >>; + + template<typename _Tp> + struct __is_endpoint<_Tp, decltype(__detail::__endpoint_reqs<_Tp>())> + : true_type + { }; + + // Check Protocol requirements for extensible implementations. + template<typename _Tp, typename = void> + struct __is_protocol + : false_type { }; + + template<typename _Tp> + auto + __protocol_reqs(const _Tp* __a = nullptr) + -> enable_if_t<__and_< + is_copy_constructible<_Tp>, is_copy_assignable<_Tp>, + __is_endpoint<typename _Tp::endpoint>, + is_same<decltype(__a->family()), int>, + is_same<decltype(__a->type()), int>, + is_same<decltype(__a->protocol()), int> + >::value>; + + template<typename _Tp> + struct __is_protocol<_Tp, decltype(__detail::__protocol_reqs<_Tp>())> + : true_type + { }; + + // Check AcceptableProtocol requirements + template<typename _Tp, typename = void> + struct __is_acceptable_protocol + : false_type { }; + + template<typename _Tp> + struct __is_acceptable_protocol<_Tp, __void_t<typename _Tp::socket>> + : __and_<__is_protocol<_Tp>, is_move_constructible<typename _Tp::socket>, + is_convertible<typename _Tp::socket*, basic_socket<_Tp>*>>::type + { }; + + // Check InternetProtocol requirements + template<typename _Tp, typename = void> + struct __is_inet_protocol + : false_type { }; + + template<typename _Tp> + auto + __inet_proto_reqs(const _Tp* __a = nullptr) + -> enable_if_t<__and_< + __is_acceptable_protocol<_Tp>, + is_same<typename _Tp::resolver, ip::basic_resolver<_Tp>>, + is_same<decltype(_Tp::v4()), _Tp>, + is_same<decltype(_Tp::v6()), _Tp>, + is_convertible<decltype(*__a == *__a), bool>, + is_convertible<decltype(*__a != *__a), bool> + >::value>; + + template<typename _Tp> + struct __is_inet_protocol<_Tp, decltype(__inet_proto_reqs<_Tp>())> + : true_type { }; + + // Variable templates for requirements (with same names as concepts above). + + template<typename _Tp> + constexpr bool __endpoint = __is_endpoint<_Tp>::value; + template<typename _Tp> + constexpr bool __protocol = __is_protocol<_Tp>::value; + template<typename _Tp> + constexpr bool __acceptable_protocol = __is_acceptable_protocol<_Tp>::value; +#endif +} // namespace __detail + /// @} } // namespace v1 diff --git a/libstdc++-v3/include/experimental/socket b/libstdc++-v3/include/experimental/socket index 80fb21da95c..84d23ebe37c 100644 --- a/libstdc++-v3/include/experimental/socket +++ b/libstdc++-v3/include/experimental/socket @@ -122,33 +122,7 @@ inline namespace v1 make_error_condition(socket_errc __e) noexcept { return error_condition(static_cast<int>(__e), socket_category()); } - template<typename _Tp, typename = __void_t<>> - struct __is_endpoint_impl : false_type - { }; - - // Check Endpoint requirements. - template<typename _Tp> - auto - __endpoint_reqs(const _Tp* __a = 0) - -> enable_if_t<__and_< - is_default_constructible<_Tp>, - __is_value_constructible<_Tp>, - is_same<decltype(__a->__protocol()), typename _Tp::protocol_type> - >::value, - __void_t< typename _Tp::protocol_type::endpoint >>; - - template<typename _Tp> - struct __is_endpoint_impl<_Tp, decltype(__endpoint_reqs<_Tp>())> - : true_type - { }; - - template<typename _Tp> - struct __is_endpoint : __is_endpoint_impl<_Tp> - { }; - - // TODO Endpoint reqs for extensible implementations - // TODO _Protocol reqs - // TODO AcceptableProtocol reqs + // TODO GettableSocket reqs // TODO SettableSocket reqs // TODO BooleanSocketOption reqs @@ -713,6 +687,9 @@ inline namespace v1 using protocol_type = _Protocol; using endpoint_type = typename protocol_type::endpoint; + static_assert(__detail::__protocol<protocol_type>, + "protocol_type meets the Protocol requirements"); + // basic_socket operations: executor_type get_executor() noexcept { return __base::get_executor(); } @@ -1853,6 +1830,9 @@ inline namespace v1 using endpoint_type = typename protocol_type::endpoint; using socket_type = typename protocol_type::socket; + static_assert(__detail::__acceptable_protocol<protocol_type>, + "protocol_type meets the AcceptableProtocol requirements"); + // construct / copy / destroy: explicit
reply other threads:[~2020-05-26 4:37 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200526043702.8C62D395CC54@sourceware.org \ --to=aoliva@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ --cc=libstdc++-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).