Skip to content

Commit

Permalink
Fix is_buffer_sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
karzhenkov committed Jul 3, 2019
1 parent 2a1f688 commit fb247ee
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 74 deletions.
107 changes: 33 additions & 74 deletions asio/include/asio/detail/is_buffer_sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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"

Expand All @@ -29,8 +31,6 @@ namespace detail {

struct buffer_sequence_memfns_base
{
void begin();
void end();
void size();
void max_size();
void capacity();
Expand All @@ -53,48 +53,6 @@ struct buffer_sequence_memfns_check
{
};

template <typename>
char (&buffer_sequence_begin_helper(...))[2];

#if defined(ASIO_HAS_DECLTYPE)

template <typename T>
char buffer_sequence_begin_helper(T* t,
typename enable_if<!is_same<
decltype(asio::buffer_sequence_begin(*t)),
void>::value>::type*);

#else // defined(ASIO_HAS_DECLTYPE)

template <typename T>
char buffer_sequence_begin_helper(T* t,
buffer_sequence_memfns_check<
void (buffer_sequence_memfns_base::*)(),
&buffer_sequence_memfns_derived<T>::begin>*);

#endif // defined(ASIO_HAS_DECLTYPE)

template <typename>
char (&buffer_sequence_end_helper(...))[2];

#if defined(ASIO_HAS_DECLTYPE)

template <typename T>
char buffer_sequence_end_helper(T* t,
typename enable_if<!is_same<
decltype(asio::buffer_sequence_end(*t)),
void>::value>::type*);

#else // defined(ASIO_HAS_DECLTYPE)

template <typename T>
char buffer_sequence_end_helper(T* t,
buffer_sequence_memfns_check<
void (buffer_sequence_memfns_base::*)(),
&buffer_sequence_memfns_derived<T>::end>*);

#endif // defined(ASIO_HAS_DECLTYPE)

template <typename>
char (&size_memfn_helper(...))[2];

Expand Down Expand Up @@ -176,27 +134,6 @@ char shrink_memfn_helper(
void (buffer_sequence_memfns_base::*)(),
&buffer_sequence_memfns_derived<T>::shrink>*);

template <typename, typename>
char (&buffer_sequence_element_type_helper(...))[2];

#if defined(ASIO_HAS_DECLTYPE)

template <typename T, typename Buffer>
char buffer_sequence_element_type_helper(T* t,
typename enable_if<is_convertible<
decltype(*asio::buffer_sequence_begin(*t)),
Buffer>::value>::type*);

#else // defined(ASIO_HAS_DECLTYPE)

template <typename T, typename Buffer>
char buffer_sequence_element_type_helper(
typename T::const_iterator*,
typename enable_if<is_convertible<
typename T::value_type, Buffer>::value>::type*);

#endif // defined(ASIO_HAS_DECLTYPE)

template <typename>
char (&const_buffers_type_typedef_helper(...))[2];

Expand All @@ -211,20 +148,42 @@ template <typename T>
char mutable_buffers_type_typedef_helper(
typename T::mutable_buffers_type*);

template <typename T, typename Buffer>
struct is_buffer_sequence_class
: integral_constant<bool,
sizeof(buffer_sequence_begin_helper<T>(0)) != 1 &&
sizeof(buffer_sequence_end_helper<T>(0)) != 1 &&
sizeof(buffer_sequence_element_type_helper<T, Buffer>(0, 0)) == 1>
template <typename Buffer>
struct is_buffer_sequence_class : sfinae_check_base
{
template <typename T>
static result<sizeof(

// Basic checks

is_convertible_to<Buffer>(*buffer_sequence_begin(declval<T&>())),
is_convertible_to<Buffer>(*buffer_sequence_end(declval<T&>())),

#if 1

// Check additional details of the inspected type

// 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.

is_convertible_to<Buffer>(*declval<T>().begin()),
is_convertible_to<Buffer>(*declval<T>().end()),

is_convertible_to<Buffer>(declval<typename T::value_type>()),

check<typename T::const_iterator>(),

#endif

0)> detector(int);
};

template <typename T, typename Buffer>
struct is_buffer_sequence
: conditional<is_class<T>::value,
is_buffer_sequence_class<T, Buffer>,
false_type>::type
: sfinae_result<is_buffer_sequence_class<Buffer>, T>
{
};

Expand Down
65 changes: 65 additions & 0 deletions asio/include/asio/detail/sfinae_helpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// 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 <typename C>
struct sfinae_result_helper : C
{
using C::detector;

template <typename>
static char(&detector(...))[2];
};

template <typename C, typename T>
struct sfinae_result
: integral_constant<bool,
sizeof(sfinae_result_helper<C>::template detector<T>(0)) == 1>
{
};

template <typename C>
struct sfinae_result<C, void> : false_type
{
};

struct sfinae_check_base
{
template <int N> struct result { };

template <typename To, typename From>
static typename enable_if<
is_convertible<From, To>::value>::type
is_convertible_to(From);

template <typename T>
static void check();
};

} // namespace detail
} // namespace asio

#include "asio/detail/pop_options.hpp"

#endif // ASIO_DETAIL_SFINAE_HELPERS_HPP
3 changes: 3 additions & 0 deletions asio/include/asio/detail/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# include <boost/type_traits/add_const.hpp>
# include <boost/type_traits/conditional.hpp>
# include <boost/type_traits/decay.hpp>
# include <boost/type_traits/declval.hpp>
# include <boost/type_traits/integral_constant.hpp>
# include <boost/type_traits/is_base_of.hpp>
# include <boost/type_traits/is_class.hpp>
Expand All @@ -42,6 +43,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;
Expand All @@ -67,6 +69,7 @@ template <bool Condition, typename Type = void>
struct enable_if : boost::enable_if_c<Condition, Type> {};
using boost::conditional;
using boost::decay;
using boost::declval;
using boost::false_type;
using boost::integral_constant;
using boost::is_base_of;
Expand Down

0 comments on commit fb247ee

Please sign in to comment.