Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:55

0001 //
0002 // impl/connect.hpp
0003 // ~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_IMPL_CONNECT_HPP
0012 #define BOOST_ASIO_IMPL_CONNECT_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <algorithm>
0019 #include <boost/asio/associator.hpp>
0020 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0021 #include <boost/asio/detail/bind_handler.hpp>
0022 #include <boost/asio/detail/handler_cont_helpers.hpp>
0023 #include <boost/asio/detail/handler_tracking.hpp>
0024 #include <boost/asio/detail/handler_type_requirements.hpp>
0025 #include <boost/asio/detail/non_const_lvalue.hpp>
0026 #include <boost/asio/detail/throw_error.hpp>
0027 #include <boost/asio/detail/type_traits.hpp>
0028 #include <boost/asio/error.hpp>
0029 #include <boost/asio/post.hpp>
0030 
0031 #include <boost/asio/detail/push_options.hpp>
0032 
0033 namespace boost {
0034 namespace asio {
0035 
0036 namespace detail
0037 {
0038   struct default_connect_condition
0039   {
0040     template <typename Endpoint>
0041     bool operator()(const boost::system::error_code&, const Endpoint&)
0042     {
0043       return true;
0044     }
0045   };
0046 
0047   template <typename Protocol, typename Iterator>
0048   inline typename Protocol::endpoint deref_connect_result(
0049       Iterator iter, boost::system::error_code& ec)
0050   {
0051     return ec ? typename Protocol::endpoint() : *iter;
0052   }
0053 
0054   template <typename T, typename Iterator>
0055   struct legacy_connect_condition_helper : T
0056   {
0057     typedef char (*fallback_func_type)(...);
0058     operator fallback_func_type() const;
0059   };
0060 
0061   template <typename R, typename Arg1, typename Arg2, typename Iterator>
0062   struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator>
0063   {
0064     R operator()(Arg1, Arg2) const;
0065     char operator()(...) const;
0066   };
0067 
0068   template <typename T, typename Iterator>
0069   struct is_legacy_connect_condition
0070   {
0071     static char asio_connect_condition_check(char);
0072     static char (&asio_connect_condition_check(Iterator))[2];
0073 
0074     static const bool value =
0075       sizeof(asio_connect_condition_check(
0076         (declval<legacy_connect_condition_helper<T, Iterator>>())(
0077           declval<const boost::system::error_code>(),
0078           declval<const Iterator>()))) != 1;
0079   };
0080 
0081   template <typename ConnectCondition, typename Iterator>
0082   inline Iterator call_connect_condition(ConnectCondition& connect_condition,
0083       const boost::system::error_code& ec, Iterator next, Iterator end,
0084       enable_if_t<is_legacy_connect_condition<
0085         ConnectCondition, Iterator>::value>* = 0)
0086   {
0087     if (next != end)
0088       return connect_condition(ec, next);
0089     return end;
0090   }
0091 
0092   template <typename ConnectCondition, typename Iterator>
0093   inline Iterator call_connect_condition(ConnectCondition& connect_condition,
0094       const boost::system::error_code& ec, Iterator next, Iterator end,
0095       enable_if_t<!is_legacy_connect_condition<
0096         ConnectCondition, Iterator>::value>* = 0)
0097   {
0098     for (;next != end; ++next)
0099       if (connect_condition(ec, *next))
0100         return next;
0101     return end;
0102   }
0103 }
0104 
0105 template <typename Protocol, typename Executor, typename EndpointSequence>
0106 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0107     const EndpointSequence& endpoints,
0108     constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
0109 {
0110   boost::system::error_code ec;
0111   typename Protocol::endpoint result = connect(s, endpoints, ec);
0112   boost::asio::detail::throw_error(ec, "connect");
0113   return result;
0114 }
0115 
0116 template <typename Protocol, typename Executor, typename EndpointSequence>
0117 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0118     const EndpointSequence& endpoints, boost::system::error_code& ec,
0119     constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
0120 {
0121   return detail::deref_connect_result<Protocol>(
0122       connect(s, endpoints.begin(), endpoints.end(),
0123         detail::default_connect_condition(), ec), ec);
0124 }
0125 
0126 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0127 template <typename Protocol, typename Executor, typename Iterator>
0128 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0129     constraint_t<!is_endpoint_sequence<Iterator>::value>)
0130 {
0131   boost::system::error_code ec;
0132   Iterator result = connect(s, begin, ec);
0133   boost::asio::detail::throw_error(ec, "connect");
0134   return result;
0135 }
0136 
0137 template <typename Protocol, typename Executor, typename Iterator>
0138 inline Iterator connect(basic_socket<Protocol, Executor>& s,
0139     Iterator begin, boost::system::error_code& ec,
0140     constraint_t<!is_endpoint_sequence<Iterator>::value>)
0141 {
0142   return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
0143 }
0144 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0145 
0146 template <typename Protocol, typename Executor, typename Iterator>
0147 Iterator connect(basic_socket<Protocol, Executor>& s,
0148     Iterator begin, Iterator end)
0149 {
0150   boost::system::error_code ec;
0151   Iterator result = connect(s, begin, end, ec);
0152   boost::asio::detail::throw_error(ec, "connect");
0153   return result;
0154 }
0155 
0156 template <typename Protocol, typename Executor, typename Iterator>
0157 inline Iterator connect(basic_socket<Protocol, Executor>& s,
0158     Iterator begin, Iterator end, boost::system::error_code& ec)
0159 {
0160   return connect(s, begin, end, detail::default_connect_condition(), ec);
0161 }
0162 
0163 template <typename Protocol, typename Executor,
0164     typename EndpointSequence, typename ConnectCondition>
0165 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0166     const EndpointSequence& endpoints, ConnectCondition connect_condition,
0167     constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
0168 {
0169   boost::system::error_code ec;
0170   typename Protocol::endpoint result = connect(
0171       s, endpoints, connect_condition, ec);
0172   boost::asio::detail::throw_error(ec, "connect");
0173   return result;
0174 }
0175 
0176 template <typename Protocol, typename Executor,
0177     typename EndpointSequence, typename ConnectCondition>
0178 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0179     const EndpointSequence& endpoints, ConnectCondition connect_condition,
0180     boost::system::error_code& ec,
0181     constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
0182 {
0183   return detail::deref_connect_result<Protocol>(
0184       connect(s, endpoints.begin(), endpoints.end(),
0185         connect_condition, ec), ec);
0186 }
0187 
0188 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0189 template <typename Protocol, typename Executor,
0190     typename Iterator, typename ConnectCondition>
0191 Iterator connect(basic_socket<Protocol, Executor>& s,
0192     Iterator begin, ConnectCondition connect_condition,
0193     constraint_t<!is_endpoint_sequence<Iterator>::value>)
0194 {
0195   boost::system::error_code ec;
0196   Iterator result = connect(s, begin, connect_condition, ec);
0197   boost::asio::detail::throw_error(ec, "connect");
0198   return result;
0199 }
0200 
0201 template <typename Protocol, typename Executor,
0202     typename Iterator, typename ConnectCondition>
0203 inline Iterator connect(basic_socket<Protocol, Executor>& s,
0204     Iterator begin, ConnectCondition connect_condition,
0205     boost::system::error_code& ec,
0206     constraint_t<!is_endpoint_sequence<Iterator>::value>)
0207 {
0208   return connect(s, begin, Iterator(), connect_condition, ec);
0209 }
0210 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0211 
0212 template <typename Protocol, typename Executor,
0213     typename Iterator, typename ConnectCondition>
0214 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0215     Iterator end, ConnectCondition connect_condition)
0216 {
0217   boost::system::error_code ec;
0218   Iterator result = connect(s, begin, end, connect_condition, ec);
0219   boost::asio::detail::throw_error(ec, "connect");
0220   return result;
0221 }
0222 
0223 template <typename Protocol, typename Executor,
0224     typename Iterator, typename ConnectCondition>
0225 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0226     Iterator end, ConnectCondition connect_condition,
0227     boost::system::error_code& ec)
0228 {
0229   ec = boost::system::error_code();
0230 
0231   for (Iterator iter = begin; iter != end; ++iter)
0232   {
0233     iter = (detail::call_connect_condition(connect_condition, ec, iter, end));
0234     if (iter != end)
0235     {
0236       s.close(ec);
0237       s.connect(*iter, ec);
0238       if (!ec)
0239         return iter;
0240     }
0241     else
0242       break;
0243   }
0244 
0245   if (!ec)
0246     ec = boost::asio::error::not_found;
0247 
0248   return end;
0249 }
0250 
0251 namespace detail
0252 {
0253   // Enable the empty base class optimisation for the connect condition.
0254   template <typename ConnectCondition>
0255   class base_from_connect_condition
0256   {
0257   protected:
0258     explicit base_from_connect_condition(
0259         const ConnectCondition& connect_condition)
0260       : connect_condition_(connect_condition)
0261     {
0262     }
0263 
0264     template <typename Iterator>
0265     void check_condition(const boost::system::error_code& ec,
0266         Iterator& iter, Iterator& end)
0267     {
0268       iter = detail::call_connect_condition(connect_condition_, ec, iter, end);
0269     }
0270 
0271   private:
0272     ConnectCondition connect_condition_;
0273   };
0274 
0275   // The default_connect_condition implementation is essentially a no-op. This
0276   // template specialisation lets us eliminate all costs associated with it.
0277   template <>
0278   class base_from_connect_condition<default_connect_condition>
0279   {
0280   protected:
0281     explicit base_from_connect_condition(const default_connect_condition&)
0282     {
0283     }
0284 
0285     template <typename Iterator>
0286     void check_condition(const boost::system::error_code&, Iterator&, Iterator&)
0287     {
0288     }
0289   };
0290 
0291   template <typename Protocol, typename Executor, typename EndpointSequence,
0292       typename ConnectCondition, typename RangeConnectHandler>
0293   class range_connect_op
0294     : public base_from_cancellation_state<RangeConnectHandler>,
0295       base_from_connect_condition<ConnectCondition>
0296   {
0297   public:
0298     range_connect_op(basic_socket<Protocol, Executor>& sock,
0299         const EndpointSequence& endpoints,
0300         const ConnectCondition& connect_condition,
0301         RangeConnectHandler& handler)
0302       : base_from_cancellation_state<RangeConnectHandler>(
0303           handler, enable_partial_cancellation()),
0304         base_from_connect_condition<ConnectCondition>(connect_condition),
0305         socket_(sock),
0306         endpoints_(endpoints),
0307         index_(0),
0308         start_(0),
0309         handler_(static_cast<RangeConnectHandler&&>(handler))
0310     {
0311     }
0312 
0313     range_connect_op(const range_connect_op& other)
0314       : base_from_cancellation_state<RangeConnectHandler>(other),
0315         base_from_connect_condition<ConnectCondition>(other),
0316         socket_(other.socket_),
0317         endpoints_(other.endpoints_),
0318         index_(other.index_),
0319         start_(other.start_),
0320         handler_(other.handler_)
0321     {
0322     }
0323 
0324     range_connect_op(range_connect_op&& other)
0325       : base_from_cancellation_state<RangeConnectHandler>(
0326           static_cast<base_from_cancellation_state<RangeConnectHandler>&&>(
0327             other)),
0328         base_from_connect_condition<ConnectCondition>(other),
0329         socket_(other.socket_),
0330         endpoints_(other.endpoints_),
0331         index_(other.index_),
0332         start_(other.start_),
0333         handler_(static_cast<RangeConnectHandler&&>(other.handler_))
0334     {
0335     }
0336 
0337     void operator()(boost::system::error_code ec, int start = 0)
0338     {
0339       this->process(ec, start,
0340           const_cast<const EndpointSequence&>(endpoints_).begin(),
0341           const_cast<const EndpointSequence&>(endpoints_).end());
0342     }
0343 
0344   //private:
0345     template <typename Iterator>
0346     void process(boost::system::error_code ec,
0347         int start, Iterator begin, Iterator end)
0348     {
0349       Iterator iter = begin;
0350       std::advance(iter, index_);
0351 
0352       switch (start_ = start)
0353       {
0354         case 1:
0355         for (;;)
0356         {
0357           this->check_condition(ec, iter, end);
0358           index_ = std::distance(begin, iter);
0359 
0360           if (iter != end)
0361           {
0362             socket_.close(ec);
0363             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0364             socket_.async_connect(*iter,
0365                 static_cast<range_connect_op&&>(*this));
0366             return;
0367           }
0368 
0369           if (start)
0370           {
0371             ec = boost::asio::error::not_found;
0372             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0373             boost::asio::post(socket_.get_executor(),
0374                 detail::bind_handler(
0375                   static_cast<range_connect_op&&>(*this), ec));
0376             return;
0377           }
0378 
0379           /* fall-through */ default:
0380 
0381           if (iter == end)
0382             break;
0383 
0384           if (!socket_.is_open())
0385           {
0386             ec = boost::asio::error::operation_aborted;
0387             break;
0388           }
0389 
0390           if (!ec)
0391             break;
0392 
0393           if (this->cancelled() != cancellation_type::none)
0394           {
0395             ec = boost::asio::error::operation_aborted;
0396             break;
0397           }
0398 
0399           ++iter;
0400           ++index_;
0401         }
0402 
0403         static_cast<RangeConnectHandler&&>(handler_)(
0404             static_cast<const boost::system::error_code&>(ec),
0405             static_cast<const typename Protocol::endpoint&>(
0406               ec || iter == end ? typename Protocol::endpoint() : *iter));
0407       }
0408     }
0409 
0410     basic_socket<Protocol, Executor>& socket_;
0411     EndpointSequence endpoints_;
0412     std::size_t index_;
0413     int start_;
0414     RangeConnectHandler handler_;
0415   };
0416 
0417   template <typename Protocol, typename Executor, typename EndpointSequence,
0418       typename ConnectCondition, typename RangeConnectHandler>
0419   inline bool asio_handler_is_continuation(
0420       range_connect_op<Protocol, Executor, EndpointSequence,
0421         ConnectCondition, RangeConnectHandler>* this_handler)
0422   {
0423     return boost_asio_handler_cont_helpers::is_continuation(
0424         this_handler->handler_);
0425   }
0426 
0427   template <typename Protocol, typename Executor>
0428   class initiate_async_range_connect
0429   {
0430   public:
0431     typedef Executor executor_type;
0432 
0433     explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)
0434       : socket_(s)
0435     {
0436     }
0437 
0438     executor_type get_executor() const noexcept
0439     {
0440       return socket_.get_executor();
0441     }
0442 
0443     template <typename RangeConnectHandler,
0444         typename EndpointSequence, typename ConnectCondition>
0445     void operator()(RangeConnectHandler&& handler,
0446         const EndpointSequence& endpoints,
0447         const ConnectCondition& connect_condition) const
0448     {
0449       // If you get an error on the following line it means that your
0450       // handler does not meet the documented type requirements for an
0451       // RangeConnectHandler.
0452       BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
0453           handler, typename Protocol::endpoint) type_check;
0454 
0455       non_const_lvalue<RangeConnectHandler> handler2(handler);
0456       range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
0457         decay_t<RangeConnectHandler>>(socket_, endpoints,
0458           connect_condition, handler2.value)(boost::system::error_code(), 1);
0459     }
0460 
0461   private:
0462     basic_socket<Protocol, Executor>& socket_;
0463   };
0464 
0465   template <typename Protocol, typename Executor, typename Iterator,
0466       typename ConnectCondition, typename IteratorConnectHandler>
0467   class iterator_connect_op
0468     : public base_from_cancellation_state<IteratorConnectHandler>,
0469       base_from_connect_condition<ConnectCondition>
0470   {
0471   public:
0472     iterator_connect_op(basic_socket<Protocol, Executor>& sock,
0473         const Iterator& begin, const Iterator& end,
0474         const ConnectCondition& connect_condition,
0475         IteratorConnectHandler& handler)
0476       : base_from_cancellation_state<IteratorConnectHandler>(
0477           handler, enable_partial_cancellation()),
0478         base_from_connect_condition<ConnectCondition>(connect_condition),
0479         socket_(sock),
0480         iter_(begin),
0481         end_(end),
0482         start_(0),
0483         handler_(static_cast<IteratorConnectHandler&&>(handler))
0484     {
0485     }
0486 
0487     iterator_connect_op(const iterator_connect_op& other)
0488       : base_from_cancellation_state<IteratorConnectHandler>(other),
0489         base_from_connect_condition<ConnectCondition>(other),
0490         socket_(other.socket_),
0491         iter_(other.iter_),
0492         end_(other.end_),
0493         start_(other.start_),
0494         handler_(other.handler_)
0495     {
0496     }
0497 
0498     iterator_connect_op(iterator_connect_op&& other)
0499       : base_from_cancellation_state<IteratorConnectHandler>(
0500           static_cast<base_from_cancellation_state<IteratorConnectHandler>&&>(
0501             other)),
0502         base_from_connect_condition<ConnectCondition>(other),
0503         socket_(other.socket_),
0504         iter_(other.iter_),
0505         end_(other.end_),
0506         start_(other.start_),
0507         handler_(static_cast<IteratorConnectHandler&&>(other.handler_))
0508     {
0509     }
0510 
0511     void operator()(boost::system::error_code ec, int start = 0)
0512     {
0513       switch (start_ = start)
0514       {
0515         case 1:
0516         for (;;)
0517         {
0518           this->check_condition(ec, iter_, end_);
0519 
0520           if (iter_ != end_)
0521           {
0522             socket_.close(ec);
0523             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0524             socket_.async_connect(*iter_,
0525                 static_cast<iterator_connect_op&&>(*this));
0526             return;
0527           }
0528 
0529           if (start)
0530           {
0531             ec = boost::asio::error::not_found;
0532             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0533             boost::asio::post(socket_.get_executor(),
0534                 detail::bind_handler(
0535                   static_cast<iterator_connect_op&&>(*this), ec));
0536             return;
0537           }
0538 
0539           /* fall-through */ default:
0540 
0541           if (iter_ == end_)
0542             break;
0543 
0544           if (!socket_.is_open())
0545           {
0546             ec = boost::asio::error::operation_aborted;
0547             break;
0548           }
0549 
0550           if (!ec)
0551             break;
0552 
0553           if (this->cancelled() != cancellation_type::none)
0554           {
0555             ec = boost::asio::error::operation_aborted;
0556             break;
0557           }
0558 
0559           ++iter_;
0560         }
0561 
0562         static_cast<IteratorConnectHandler&&>(handler_)(
0563             static_cast<const boost::system::error_code&>(ec),
0564             static_cast<const Iterator&>(iter_));
0565       }
0566     }
0567 
0568   //private:
0569     basic_socket<Protocol, Executor>& socket_;
0570     Iterator iter_;
0571     Iterator end_;
0572     int start_;
0573     IteratorConnectHandler handler_;
0574   };
0575 
0576   template <typename Protocol, typename Executor, typename Iterator,
0577       typename ConnectCondition, typename IteratorConnectHandler>
0578   inline bool asio_handler_is_continuation(
0579       iterator_connect_op<Protocol, Executor, Iterator,
0580         ConnectCondition, IteratorConnectHandler>* this_handler)
0581   {
0582     return boost_asio_handler_cont_helpers::is_continuation(
0583         this_handler->handler_);
0584   }
0585 
0586   template <typename Protocol, typename Executor>
0587   class initiate_async_iterator_connect
0588   {
0589   public:
0590     typedef Executor executor_type;
0591 
0592     explicit initiate_async_iterator_connect(
0593         basic_socket<Protocol, Executor>& s)
0594       : socket_(s)
0595     {
0596     }
0597 
0598     executor_type get_executor() const noexcept
0599     {
0600       return socket_.get_executor();
0601     }
0602 
0603     template <typename IteratorConnectHandler,
0604         typename Iterator, typename ConnectCondition>
0605     void operator()(IteratorConnectHandler&& handler,
0606         Iterator begin, Iterator end,
0607         const ConnectCondition& connect_condition) const
0608     {
0609       // If you get an error on the following line it means that your
0610       // handler does not meet the documented type requirements for an
0611       // IteratorConnectHandler.
0612       BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
0613           IteratorConnectHandler, handler, Iterator) type_check;
0614 
0615       non_const_lvalue<IteratorConnectHandler> handler2(handler);
0616       iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
0617         decay_t<IteratorConnectHandler>>(socket_, begin, end,
0618           connect_condition, handler2.value)(boost::system::error_code(), 1);
0619     }
0620 
0621   private:
0622     basic_socket<Protocol, Executor>& socket_;
0623   };
0624 } // namespace detail
0625 
0626 #if !defined(GENERATING_DOCUMENTATION)
0627 
0628 template <template <typename, typename> class Associator,
0629     typename Protocol, typename Executor, typename EndpointSequence,
0630     typename ConnectCondition, typename RangeConnectHandler,
0631     typename DefaultCandidate>
0632 struct associator<Associator,
0633     detail::range_connect_op<Protocol, Executor,
0634       EndpointSequence, ConnectCondition, RangeConnectHandler>,
0635     DefaultCandidate>
0636   : Associator<RangeConnectHandler, DefaultCandidate>
0637 {
0638   static typename Associator<RangeConnectHandler, DefaultCandidate>::type get(
0639       const detail::range_connect_op<Protocol, Executor, EndpointSequence,
0640         ConnectCondition, RangeConnectHandler>& h) noexcept
0641   {
0642     return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_);
0643   }
0644 
0645   static auto get(
0646       const detail::range_connect_op<Protocol, Executor,
0647         EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
0648       const DefaultCandidate& c) noexcept
0649     -> decltype(
0650       Associator<RangeConnectHandler, DefaultCandidate>::get(
0651         h.handler_, c))
0652   {
0653     return Associator<RangeConnectHandler, DefaultCandidate>::get(
0654         h.handler_, c);
0655   }
0656 };
0657 
0658 template <template <typename, typename> class Associator,
0659     typename Protocol, typename Executor, typename Iterator,
0660     typename ConnectCondition, typename IteratorConnectHandler,
0661     typename DefaultCandidate>
0662 struct associator<Associator,
0663     detail::iterator_connect_op<Protocol, Executor,
0664       Iterator, ConnectCondition, IteratorConnectHandler>,
0665     DefaultCandidate>
0666   : Associator<IteratorConnectHandler, DefaultCandidate>
0667 {
0668   static typename Associator<IteratorConnectHandler, DefaultCandidate>::type
0669   get(const detail::iterator_connect_op<Protocol, Executor, Iterator,
0670         ConnectCondition, IteratorConnectHandler>& h) noexcept
0671   {
0672     return Associator<IteratorConnectHandler, DefaultCandidate>::get(
0673         h.handler_);
0674   }
0675 
0676   static auto get(
0677       const detail::iterator_connect_op<Protocol, Executor,
0678         Iterator, ConnectCondition, IteratorConnectHandler>& h,
0679       const DefaultCandidate& c) noexcept
0680     -> decltype(
0681       Associator<IteratorConnectHandler, DefaultCandidate>::get(
0682         h.handler_, c))
0683   {
0684     return Associator<IteratorConnectHandler, DefaultCandidate>::get(
0685         h.handler_, c);
0686   }
0687 };
0688 
0689 #endif // !defined(GENERATING_DOCUMENTATION)
0690 
0691 template <typename Protocol, typename Executor, typename EndpointSequence,
0692     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0693       typename Protocol::endpoint)) RangeConnectToken>
0694 inline auto async_connect(basic_socket<Protocol, Executor>& s,
0695     const EndpointSequence& endpoints, RangeConnectToken&& token,
0696     constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
0697   -> decltype(
0698     async_initiate<RangeConnectToken,
0699       void (boost::system::error_code, typename Protocol::endpoint)>(
0700         declval<detail::initiate_async_range_connect<Protocol, Executor>>(),
0701         token, endpoints, declval<detail::default_connect_condition>()))
0702 {
0703   return async_initiate<RangeConnectToken,
0704     void (boost::system::error_code, typename Protocol::endpoint)>(
0705       detail::initiate_async_range_connect<Protocol, Executor>(s),
0706       token, endpoints, detail::default_connect_condition());
0707 }
0708 
0709 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0710 template <typename Protocol, typename Executor, typename Iterator,
0711     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0712       Iterator)) IteratorConnectToken>
0713 inline auto async_connect(basic_socket<Protocol, Executor>& s,
0714     Iterator begin, IteratorConnectToken&& token,
0715     constraint_t<!is_endpoint_sequence<Iterator>::value>)
0716   -> decltype(
0717     async_initiate<IteratorConnectToken,
0718       void (boost::system::error_code, Iterator)>(
0719         declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
0720         token, begin, Iterator(), declval<detail::default_connect_condition>()))
0721 {
0722   return async_initiate<IteratorConnectToken,
0723     void (boost::system::error_code, Iterator)>(
0724       detail::initiate_async_iterator_connect<Protocol, Executor>(s),
0725       token, begin, Iterator(), detail::default_connect_condition());
0726 }
0727 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0728 
0729 template <typename Protocol, typename Executor, typename Iterator,
0730     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0731       Iterator)) IteratorConnectToken>
0732 inline auto async_connect(basic_socket<Protocol, Executor>& s,
0733     Iterator begin, Iterator end, IteratorConnectToken&& token)
0734   -> decltype(
0735     async_initiate<IteratorConnectToken,
0736       void (boost::system::error_code, Iterator)>(
0737         declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
0738         token, begin, end, declval<detail::default_connect_condition>()))
0739 {
0740   return async_initiate<IteratorConnectToken,
0741     void (boost::system::error_code, Iterator)>(
0742       detail::initiate_async_iterator_connect<Protocol, Executor>(s),
0743       token, begin, end, detail::default_connect_condition());
0744 }
0745 
0746 template <typename Protocol, typename Executor,
0747     typename EndpointSequence, typename ConnectCondition,
0748     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0749       typename Protocol::endpoint)) RangeConnectToken>
0750 inline auto async_connect(basic_socket<Protocol, Executor>& s,
0751     const EndpointSequence& endpoints, ConnectCondition connect_condition,
0752     RangeConnectToken&& token,
0753     constraint_t<is_endpoint_sequence<EndpointSequence>::value>)
0754   -> decltype(
0755     async_initiate<RangeConnectToken,
0756       void (boost::system::error_code, typename Protocol::endpoint)>(
0757         declval<detail::initiate_async_range_connect<Protocol, Executor>>(),
0758         token, endpoints, connect_condition))
0759 {
0760   return async_initiate<RangeConnectToken,
0761     void (boost::system::error_code, typename Protocol::endpoint)>(
0762       detail::initiate_async_range_connect<Protocol, Executor>(s),
0763       token, endpoints, connect_condition);
0764 }
0765 
0766 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0767 template <typename Protocol, typename Executor,
0768     typename Iterator, typename ConnectCondition,
0769     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0770       Iterator)) IteratorConnectToken>
0771 inline auto async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0772     ConnectCondition connect_condition, IteratorConnectToken&& token,
0773     constraint_t<!is_endpoint_sequence<Iterator>::value>)
0774   -> decltype(
0775     async_initiate<IteratorConnectToken,
0776       void (boost::system::error_code, Iterator)>(
0777         declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
0778         token, begin, Iterator(), connect_condition))
0779 {
0780   return async_initiate<IteratorConnectToken,
0781     void (boost::system::error_code, Iterator)>(
0782       detail::initiate_async_iterator_connect<Protocol, Executor>(s),
0783       token, begin, Iterator(), connect_condition);
0784 }
0785 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0786 
0787 template <typename Protocol, typename Executor,
0788     typename Iterator, typename ConnectCondition,
0789     BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
0790       Iterator)) IteratorConnectToken>
0791 inline auto async_connect(basic_socket<Protocol, Executor>& s,
0792     Iterator begin, Iterator end, ConnectCondition connect_condition,
0793     IteratorConnectToken&& token)
0794   -> decltype(
0795     async_initiate<IteratorConnectToken,
0796       void (boost::system::error_code, Iterator)>(
0797         declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(),
0798         token, begin, end, connect_condition))
0799 {
0800   return async_initiate<IteratorConnectToken,
0801     void (boost::system::error_code, Iterator)>(
0802       detail::initiate_async_iterator_connect<Protocol, Executor>(s),
0803       token, begin, end, connect_condition);
0804 }
0805 
0806 } // namespace asio
0807 } // namespace boost
0808 
0809 #include <boost/asio/detail/pop_options.hpp>
0810 
0811 #endif // BOOST_ASIO_IMPL_CONNECT_HPP