diff --git a/asio/include/asio/detail/is_buffer_sequence.hpp b/asio/include/asio/detail/is_buffer_sequence.hpp index 937d22215d..3561c44d7c 100644 --- a/asio/include/asio/detail/is_buffer_sequence.hpp +++ b/asio/include/asio/detail/is_buffer_sequence.hpp @@ -3,6 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2019 Alexander Karzhenkov // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,6 +18,7 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" +#include "asio/detail/sfinae_helpers.hpp" #include "asio/detail/push_options.hpp" @@ -27,204 +29,42 @@ class const_buffer; namespace detail { -struct buffer_sequence_memfns_base +template +struct is_buffer_sequence_class : sfinae_check_base { - void begin(); - void end(); - void size(); - void max_size(); - void capacity(); - void data(); - void prepare(); - void commit(); - void consume(); - void grow(); - void shrink(); -}; - -template -struct buffer_sequence_memfns_derived - : T, buffer_sequence_memfns_base -{ -}; - -template -struct buffer_sequence_memfns_check -{ -}; - -template -char (&buffer_sequence_begin_helper(...))[2]; - -#if defined(ASIO_HAS_DECLTYPE) - -template -char buffer_sequence_begin_helper(T* t, - typename enable_if::value>::type*); - -#else // defined(ASIO_HAS_DECLTYPE) - -template -char buffer_sequence_begin_helper(T* t, - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::begin>*); - -#endif // defined(ASIO_HAS_DECLTYPE) - -template -char (&buffer_sequence_end_helper(...))[2]; - -#if defined(ASIO_HAS_DECLTYPE) - -template -char buffer_sequence_end_helper(T* t, - typename enable_if::value>::type*); - -#else // defined(ASIO_HAS_DECLTYPE) - -template -char buffer_sequence_end_helper(T* t, - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::end>*); - -#endif // defined(ASIO_HAS_DECLTYPE) - -template -char (&size_memfn_helper(...))[2]; - -template -char size_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::size>*); - -template -char (&max_size_memfn_helper(...))[2]; - -template -char max_size_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::max_size>*); - -template -char (&capacity_memfn_helper(...))[2]; - -template -char capacity_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::capacity>*); + template + static result -char (&data_memfn_helper(...))[2]; + // Basic checks -template -char data_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::data>*); - -template -char (&prepare_memfn_helper(...))[2]; + is_convertible_to(*buffer_sequence_begin(declval())), + is_convertible_to(*buffer_sequence_end(declval())), -template -char prepare_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::prepare>*); +#if 1 -template -char (&commit_memfn_helper(...))[2]; - -template -char commit_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::commit>*); + // Check additional details of the inspected type -template -char (&consume_memfn_helper(...))[2]; + // Perhaps the additional checks make sense when using C++98. + // It would be better to implement them by the means + // of 'buffer_sequence_begin' and 'buffer_sequence_end'. + // Explicit specializations of 'is_buffer_sequence' + // for 'mutable_buffer' and 'const_buffer' would not be needed. -template -char consume_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::consume>*); - -template -char (&grow_memfn_helper(...))[2]; - -template -char grow_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::grow>*); + is_convertible_to(*declval().begin()), + is_convertible_to(*declval().end()), -template -char (&shrink_memfn_helper(...))[2]; + is_convertible_to(declval()), -template -char shrink_memfn_helper( - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived::shrink>*); - -template -char (&buffer_sequence_element_type_helper(...))[2]; - -#if defined(ASIO_HAS_DECLTYPE) - -template -char buffer_sequence_element_type_helper(T* t, - typename enable_if::value>::type*); - -#else // defined(ASIO_HAS_DECLTYPE) - -template -char buffer_sequence_element_type_helper( - typename T::const_iterator*, - typename enable_if::value>::type*); + check(), -#endif // defined(ASIO_HAS_DECLTYPE) +#endif -template -char (&const_buffers_type_typedef_helper(...))[2]; - -template -char const_buffers_type_typedef_helper( - typename T::const_buffers_type*); - -template -char (&mutable_buffers_type_typedef_helper(...))[2]; - -template -char mutable_buffers_type_typedef_helper( - typename T::mutable_buffers_type*); - -template -struct is_buffer_sequence_class - : integral_constant(0)) != 1 && - sizeof(buffer_sequence_end_helper(0)) != 1 && - sizeof(buffer_sequence_element_type_helper(0, 0)) == 1> -{ + 0)> detector(int); }; template struct is_buffer_sequence - : conditional::value, - is_buffer_sequence_class, - false_type>::type + : sfinae_result, T> { }; @@ -252,49 +92,53 @@ struct is_buffer_sequence { }; -template -struct is_dynamic_buffer_class_v1 - : integral_constant(0)) != 1 && - sizeof(max_size_memfn_helper(0)) != 1 && - sizeof(capacity_memfn_helper(0)) != 1 && - sizeof(data_memfn_helper(0)) != 1 && - sizeof(consume_memfn_helper(0)) != 1 && - sizeof(prepare_memfn_helper(0)) != 1 && - sizeof(commit_memfn_helper(0)) != 1 && - sizeof(const_buffers_type_typedef_helper(0)) == 1 && - sizeof(mutable_buffers_type_typedef_helper(0)) == 1> +struct is_dynamic_buffer_class_v1 : sfinae_check_base { + template + static result(), + check(), + + 0)> detector(int); }; template struct is_dynamic_buffer_v1 - : conditional::value, - is_dynamic_buffer_class_v1, - false_type>::type + : sfinae_result { }; -template -struct is_dynamic_buffer_class_v2 - : integral_constant(0)) != 1 && - sizeof(max_size_memfn_helper(0)) != 1 && - sizeof(capacity_memfn_helper(0)) != 1 && - sizeof(data_memfn_helper(0)) != 1 && - sizeof(consume_memfn_helper(0)) != 1 && - sizeof(grow_memfn_helper(0)) != 1 && - sizeof(shrink_memfn_helper(0)) != 1 && - sizeof(const_buffers_type_typedef_helper(0)) == 1 && - sizeof(mutable_buffers_type_typedef_helper(0)) == 1> +struct is_dynamic_buffer_class_v2 : sfinae_check_base { + template + static result(), + check(), + + 0)> detector(int); }; template struct is_dynamic_buffer_v2 - : conditional::value, - is_dynamic_buffer_class_v2, - false_type>::type + : sfinae_result { }; diff --git a/asio/include/asio/detail/sfinae_helpers.hpp b/asio/include/asio/detail/sfinae_helpers.hpp new file mode 100644 index 0000000000..934aee30e2 --- /dev/null +++ b/asio/include/asio/detail/sfinae_helpers.hpp @@ -0,0 +1,70 @@ +// +// detail/sfinae_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2019 Alexander Karzhenkov +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SFINAE_HELPERS_HPP +#define ASIO_DETAIL_SFINAE_HELPERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template +struct sfinae_result_helper : C +{ + using C::detector; + + template + static char(&detector(...))[2]; +}; + +template +struct sfinae_result + : integral_constant::template detector(0)) == 1> +{ +}; + +template +struct sfinae_result : false_type +{ +}; + +struct sfinae_check_base +{ + template struct result { }; + + template + static typename enable_if< + is_member_function_pointer::value>::type + is_memfn(T); + + template + static typename enable_if< + is_convertible::value>::type + is_convertible_to(From); + + template + static void check(); +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SFINAE_HELPERS_HPP diff --git a/asio/include/asio/detail/type_traits.hpp b/asio/include/asio/detail/type_traits.hpp index a2b1531f35..da27b5ac9c 100644 --- a/asio/include/asio/detail/type_traits.hpp +++ b/asio/include/asio/detail/type_traits.hpp @@ -23,12 +23,14 @@ # include # include # include +# include # include # include # include # include # include # include +# include # include # include # include @@ -42,6 +44,7 @@ namespace asio { using std::add_const; using std::conditional; using std::decay; +using std::declval; using std::enable_if; using std::false_type; using std::integral_constant; @@ -50,6 +53,7 @@ using std::is_class; using std::is_const; using std::is_convertible; using std::is_function; +using std::is_member_function_pointer; using std::is_same; using std::remove_pointer; using std::remove_reference; @@ -67,6 +71,7 @@ template struct enable_if : boost::enable_if_c {}; using boost::conditional; using boost::decay; +using boost::declval; using boost::false_type; using boost::integral_constant; using boost::is_base_of; @@ -74,6 +79,7 @@ using boost::is_class; using boost::is_const; using boost::is_convertible; using boost::is_function; +using boost::is_member_function_pointer; using boost::is_same; using boost::remove_pointer; using boost::remove_reference;