Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-12 08:08:12

0001 //
0002 // impl/connect.hpp
0003 // ~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 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   template <typename Protocol, typename Iterator>
0039   inline typename Protocol::endpoint deref_connect_result(
0040       Iterator iter, boost::system::error_code& ec)
0041   {
0042     return ec ? typename Protocol::endpoint() : *iter;
0043   }
0044 
0045   template <typename ConnectCondition, typename Iterator>
0046   inline Iterator call_connect_condition(ConnectCondition& connect_condition,
0047       const boost::system::error_code& ec, Iterator next, Iterator end,
0048       constraint_t<
0049         is_same<
0050           result_of_t<ConnectCondition(boost::system::error_code, Iterator)>,
0051           Iterator
0052         >::value
0053       > = 0)
0054   {
0055     if (next != end)
0056       return connect_condition(ec, next);
0057     return end;
0058   }
0059 
0060   template <typename ConnectCondition, typename Iterator>
0061   inline Iterator call_connect_condition(ConnectCondition& connect_condition,
0062       const boost::system::error_code& ec, Iterator next, Iterator end,
0063       constraint_t<
0064         is_same<
0065           result_of_t<ConnectCondition(boost::system::error_code,
0066             decltype(*declval<Iterator>()))>,
0067           bool
0068         >::value
0069       > = 0)
0070   {
0071     for (;next != end; ++next)
0072       if (connect_condition(ec, *next))
0073         return next;
0074     return end;
0075   }
0076 } // namespace detail
0077 
0078 template <typename Protocol, typename Executor, typename EndpointSequence>
0079 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0080     const EndpointSequence& endpoints,
0081     constraint_t<
0082       is_endpoint_sequence<EndpointSequence>::value
0083     >)
0084 {
0085   boost::system::error_code ec;
0086   typename Protocol::endpoint result = connect(s, endpoints, ec);
0087   boost::asio::detail::throw_error(ec, "connect");
0088   return result;
0089 }
0090 
0091 template <typename Protocol, typename Executor, typename EndpointSequence>
0092 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0093     const EndpointSequence& endpoints, boost::system::error_code& ec,
0094     constraint_t<
0095       is_endpoint_sequence<EndpointSequence>::value
0096     >)
0097 {
0098   return detail::deref_connect_result<Protocol>(
0099       connect(s, endpoints.begin(), endpoints.end(),
0100         detail::default_connect_condition(), ec), ec);
0101 }
0102 
0103 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0104 template <typename Protocol, typename Executor, typename Iterator>
0105 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0106     constraint_t<
0107       !is_endpoint_sequence<Iterator>::value
0108     >)
0109 {
0110   boost::system::error_code ec;
0111   Iterator result = connect(s, begin, ec);
0112   boost::asio::detail::throw_error(ec, "connect");
0113   return result;
0114 }
0115 
0116 template <typename Protocol, typename Executor, typename Iterator>
0117 inline Iterator connect(basic_socket<Protocol, Executor>& s,
0118     Iterator begin, boost::system::error_code& ec,
0119     constraint_t<
0120       !is_endpoint_sequence<Iterator>::value
0121     >)
0122 {
0123   return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
0124 }
0125 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0126 
0127 template <typename Protocol, typename Executor, typename Iterator>
0128 Iterator connect(basic_socket<Protocol, Executor>& s,
0129     Iterator begin, Iterator end)
0130 {
0131   boost::system::error_code ec;
0132   Iterator result = connect(s, begin, end, 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, Iterator end, boost::system::error_code& ec)
0140 {
0141   return connect(s, begin, end, detail::default_connect_condition(), ec);
0142 }
0143 
0144 template <typename Protocol, typename Executor,
0145     typename EndpointSequence, typename ConnectCondition>
0146 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
0147     const EndpointSequence& endpoints, ConnectCondition connect_condition,
0148     constraint_t<
0149       is_endpoint_sequence<EndpointSequence>::value
0150     >,
0151     constraint_t<
0152       is_connect_condition<ConnectCondition,
0153         decltype(declval<const EndpointSequence&>().begin())>::value
0154     >)
0155 {
0156   boost::system::error_code ec;
0157   typename Protocol::endpoint result = connect(
0158       s, endpoints, connect_condition, ec);
0159   boost::asio::detail::throw_error(ec, "connect");
0160   return result;
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     boost::system::error_code& ec,
0168     constraint_t<
0169       is_endpoint_sequence<EndpointSequence>::value
0170     >,
0171     constraint_t<
0172       is_connect_condition<ConnectCondition,
0173         decltype(declval<const EndpointSequence&>().begin())>::value
0174     >)
0175 {
0176   return detail::deref_connect_result<Protocol>(
0177       connect(s, endpoints.begin(), endpoints.end(),
0178         connect_condition, ec), ec);
0179 }
0180 
0181 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0182 template <typename Protocol, typename Executor,
0183     typename Iterator, typename ConnectCondition>
0184 Iterator connect(basic_socket<Protocol, Executor>& s,
0185     Iterator begin, ConnectCondition connect_condition,
0186     constraint_t<
0187       !is_endpoint_sequence<Iterator>::value
0188     >,
0189     constraint_t<
0190       is_connect_condition<ConnectCondition, Iterator>::value
0191     >)
0192 {
0193   boost::system::error_code ec;
0194   Iterator result = connect(s, begin, connect_condition, ec);
0195   boost::asio::detail::throw_error(ec, "connect");
0196   return result;
0197 }
0198 
0199 template <typename Protocol, typename Executor,
0200     typename Iterator, typename ConnectCondition>
0201 inline Iterator connect(basic_socket<Protocol, Executor>& s,
0202     Iterator begin, ConnectCondition connect_condition,
0203     boost::system::error_code& ec,
0204     constraint_t<
0205       !is_endpoint_sequence<Iterator>::value
0206     >,
0207     constraint_t<
0208       is_connect_condition<ConnectCondition, Iterator>::value
0209     >)
0210 {
0211   return connect(s, begin, Iterator(), connect_condition, ec);
0212 }
0213 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0214 
0215 template <typename Protocol, typename Executor,
0216     typename Iterator, typename ConnectCondition>
0217 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0218     Iterator end, ConnectCondition connect_condition,
0219     constraint_t<
0220       is_connect_condition<ConnectCondition, Iterator>::value
0221     >)
0222 {
0223   boost::system::error_code ec;
0224   Iterator result = connect(s, begin, end, connect_condition, ec);
0225   boost::asio::detail::throw_error(ec, "connect");
0226   return result;
0227 }
0228 
0229 template <typename Protocol, typename Executor,
0230     typename Iterator, typename ConnectCondition>
0231 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
0232     Iterator end, ConnectCondition connect_condition,
0233     boost::system::error_code& ec,
0234     constraint_t<
0235       is_connect_condition<ConnectCondition, Iterator>::value
0236     >)
0237 {
0238   ec = boost::system::error_code();
0239 
0240   for (Iterator iter = begin; iter != end; ++iter)
0241   {
0242     iter = (detail::call_connect_condition(connect_condition, ec, iter, end));
0243     if (iter != end)
0244     {
0245       s.close(ec);
0246       s.connect(*iter, ec);
0247       if (!ec)
0248         return iter;
0249     }
0250     else
0251       break;
0252   }
0253 
0254   if (!ec)
0255     ec = boost::asio::error::not_found;
0256 
0257   return end;
0258 }
0259 
0260 namespace detail
0261 {
0262   // Enable the empty base class optimisation for the connect condition.
0263   template <typename ConnectCondition>
0264   class base_from_connect_condition
0265   {
0266   protected:
0267     explicit base_from_connect_condition(
0268         const ConnectCondition& connect_condition)
0269       : connect_condition_(connect_condition)
0270     {
0271     }
0272 
0273     template <typename Iterator>
0274     void check_condition(const boost::system::error_code& ec,
0275         Iterator& iter, Iterator& end)
0276     {
0277       iter = detail::call_connect_condition(connect_condition_, ec, iter, end);
0278     }
0279 
0280   private:
0281     ConnectCondition connect_condition_;
0282   };
0283 
0284   // The default_connect_condition implementation is essentially a no-op. This
0285   // template specialisation lets us eliminate all costs associated with it.
0286   template <>
0287   class base_from_connect_condition<default_connect_condition>
0288   {
0289   protected:
0290     explicit base_from_connect_condition(const default_connect_condition&)
0291     {
0292     }
0293 
0294     template <typename Iterator>
0295     void check_condition(const boost::system::error_code&, Iterator&, Iterator&)
0296     {
0297     }
0298   };
0299 
0300   template <typename Protocol, typename Executor, typename EndpointSequence,
0301       typename ConnectCondition, typename RangeConnectHandler>
0302   class range_connect_op
0303     : public base_from_cancellation_state<RangeConnectHandler>,
0304       base_from_connect_condition<ConnectCondition>
0305   {
0306   public:
0307     range_connect_op(basic_socket<Protocol, Executor>& sock,
0308         const EndpointSequence& endpoints,
0309         const ConnectCondition& connect_condition,
0310         RangeConnectHandler& handler)
0311       : base_from_cancellation_state<RangeConnectHandler>(
0312           handler, enable_partial_cancellation()),
0313         base_from_connect_condition<ConnectCondition>(connect_condition),
0314         socket_(sock),
0315         endpoints_(endpoints),
0316         index_(0),
0317         start_(0),
0318         handler_(static_cast<RangeConnectHandler&&>(handler))
0319     {
0320     }
0321 
0322     range_connect_op(const range_connect_op& other)
0323       : base_from_cancellation_state<RangeConnectHandler>(other),
0324         base_from_connect_condition<ConnectCondition>(other),
0325         socket_(other.socket_),
0326         endpoints_(other.endpoints_),
0327         index_(other.index_),
0328         start_(other.start_),
0329         handler_(other.handler_)
0330     {
0331     }
0332 
0333     range_connect_op(range_connect_op&& other)
0334       : base_from_cancellation_state<RangeConnectHandler>(
0335           static_cast<base_from_cancellation_state<RangeConnectHandler>&&>(
0336             other)),
0337         base_from_connect_condition<ConnectCondition>(other),
0338         socket_(other.socket_),
0339         endpoints_(other.endpoints_),
0340         index_(other.index_),
0341         start_(other.start_),
0342         handler_(static_cast<RangeConnectHandler&&>(other.handler_))
0343     {
0344     }
0345 
0346     void operator()(boost::system::error_code ec, int start = 0)
0347     {
0348       this->process(ec, start,
0349           const_cast<const EndpointSequence&>(endpoints_).begin(),
0350           const_cast<const EndpointSequence&>(endpoints_).end());
0351     }
0352 
0353   //private:
0354     template <typename Iterator>
0355     void process(boost::system::error_code ec,
0356         int start, Iterator begin, Iterator end)
0357     {
0358       Iterator iter = begin;
0359       std::advance(iter, index_);
0360 
0361       switch (start_ = start)
0362       {
0363         case 1:
0364         for (;;)
0365         {
0366           this->check_condition(ec, iter, end);
0367           index_ = std::distance(begin, iter);
0368 
0369           if (iter != end)
0370           {
0371             socket_.close(ec);
0372             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0373             socket_.async_connect(*iter,
0374                 static_cast<range_connect_op&&>(*this));
0375             return;
0376           }
0377 
0378           if (start)
0379           {
0380             ec = boost::asio::error::not_found;
0381             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0382             boost::asio::post(socket_.get_executor(),
0383                 detail::bind_handler(
0384                   static_cast<range_connect_op&&>(*this), ec));
0385             return;
0386           }
0387 
0388           /* fall-through */ default:
0389 
0390           if (iter == end)
0391             break;
0392 
0393           if (!socket_.is_open())
0394           {
0395             ec = boost::asio::error::operation_aborted;
0396             break;
0397           }
0398 
0399           if (!ec)
0400             break;
0401 
0402           if (this->cancelled() != cancellation_type::none)
0403           {
0404             ec = boost::asio::error::operation_aborted;
0405             break;
0406           }
0407 
0408           ++iter;
0409           ++index_;
0410         }
0411 
0412         static_cast<RangeConnectHandler&&>(handler_)(
0413             static_cast<const boost::system::error_code&>(ec),
0414             static_cast<const typename Protocol::endpoint&>(
0415               ec || iter == end ? typename Protocol::endpoint() : *iter));
0416       }
0417     }
0418 
0419     basic_socket<Protocol, Executor>& socket_;
0420     EndpointSequence endpoints_;
0421     std::size_t index_;
0422     int start_;
0423     RangeConnectHandler handler_;
0424   };
0425 
0426   template <typename Protocol, typename Executor, typename EndpointSequence,
0427       typename ConnectCondition, typename RangeConnectHandler>
0428   inline bool asio_handler_is_continuation(
0429       range_connect_op<Protocol, Executor, EndpointSequence,
0430         ConnectCondition, RangeConnectHandler>* this_handler)
0431   {
0432     return boost_asio_handler_cont_helpers::is_continuation(
0433         this_handler->handler_);
0434   }
0435 
0436   template <typename Protocol, typename Executor>
0437   class initiate_async_range_connect
0438   {
0439   public:
0440     typedef Executor executor_type;
0441 
0442     explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)
0443       : socket_(s)
0444     {
0445     }
0446 
0447     executor_type get_executor() const noexcept
0448     {
0449       return socket_.get_executor();
0450     }
0451 
0452     template <typename RangeConnectHandler,
0453         typename EndpointSequence, typename ConnectCondition>
0454     void operator()(RangeConnectHandler&& handler,
0455         const EndpointSequence& endpoints,
0456         const ConnectCondition& connect_condition) const
0457     {
0458       // If you get an error on the following line it means that your
0459       // handler does not meet the documented type requirements for an
0460       // RangeConnectHandler.
0461       BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
0462           handler, typename Protocol::endpoint) type_check;
0463 
0464       non_const_lvalue<RangeConnectHandler> handler2(handler);
0465       range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
0466         decay_t<RangeConnectHandler>>(socket_, endpoints,
0467           connect_condition, handler2.value)(boost::system::error_code(), 1);
0468     }
0469 
0470   private:
0471     basic_socket<Protocol, Executor>& socket_;
0472   };
0473 
0474   template <typename Protocol, typename Executor, typename Iterator,
0475       typename ConnectCondition, typename IteratorConnectHandler>
0476   class iterator_connect_op
0477     : public base_from_cancellation_state<IteratorConnectHandler>,
0478       base_from_connect_condition<ConnectCondition>
0479   {
0480   public:
0481     iterator_connect_op(basic_socket<Protocol, Executor>& sock,
0482         const Iterator& begin, const Iterator& end,
0483         const ConnectCondition& connect_condition,
0484         IteratorConnectHandler& handler)
0485       : base_from_cancellation_state<IteratorConnectHandler>(
0486           handler, enable_partial_cancellation()),
0487         base_from_connect_condition<ConnectCondition>(connect_condition),
0488         socket_(sock),
0489         iter_(begin),
0490         end_(end),
0491         start_(0),
0492         handler_(static_cast<IteratorConnectHandler&&>(handler))
0493     {
0494     }
0495 
0496     iterator_connect_op(const iterator_connect_op& other)
0497       : base_from_cancellation_state<IteratorConnectHandler>(other),
0498         base_from_connect_condition<ConnectCondition>(other),
0499         socket_(other.socket_),
0500         iter_(other.iter_),
0501         end_(other.end_),
0502         start_(other.start_),
0503         handler_(other.handler_)
0504     {
0505     }
0506 
0507     iterator_connect_op(iterator_connect_op&& other)
0508       : base_from_cancellation_state<IteratorConnectHandler>(
0509           static_cast<base_from_cancellation_state<IteratorConnectHandler>&&>(
0510             other)),
0511         base_from_connect_condition<ConnectCondition>(other),
0512         socket_(other.socket_),
0513         iter_(other.iter_),
0514         end_(other.end_),
0515         start_(other.start_),
0516         handler_(static_cast<IteratorConnectHandler&&>(other.handler_))
0517     {
0518     }
0519 
0520     void operator()(boost::system::error_code ec, int start = 0)
0521     {
0522       switch (start_ = start)
0523       {
0524         case 1:
0525         for (;;)
0526         {
0527           this->check_condition(ec, iter_, end_);
0528 
0529           if (iter_ != end_)
0530           {
0531             socket_.close(ec);
0532             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0533             socket_.async_connect(*iter_,
0534                 static_cast<iterator_connect_op&&>(*this));
0535             return;
0536           }
0537 
0538           if (start)
0539           {
0540             ec = boost::asio::error::not_found;
0541             BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));
0542             boost::asio::post(socket_.get_executor(),
0543                 detail::bind_handler(
0544                   static_cast<iterator_connect_op&&>(*this), ec));
0545             return;
0546           }
0547 
0548           /* fall-through */ default:
0549 
0550           if (iter_ == end_)
0551             break;
0552 
0553           if (!socket_.is_open())
0554           {
0555             ec = boost::asio::error::operation_aborted;
0556             break;
0557           }
0558 
0559           if (!ec)
0560             break;
0561 
0562           if (this->cancelled() != cancellation_type::none)
0563           {
0564             ec = boost::asio::error::operation_aborted;
0565             break;
0566           }
0567 
0568           ++iter_;
0569         }
0570 
0571         static_cast<IteratorConnectHandler&&>(handler_)(
0572             static_cast<const boost::system::error_code&>(ec),
0573             static_cast<const Iterator&>(iter_));
0574       }
0575     }
0576 
0577   //private:
0578     basic_socket<Protocol, Executor>& socket_;
0579     Iterator iter_;
0580     Iterator end_;
0581     int start_;
0582     IteratorConnectHandler handler_;
0583   };
0584 
0585   template <typename Protocol, typename Executor, typename Iterator,
0586       typename ConnectCondition, typename IteratorConnectHandler>
0587   inline bool asio_handler_is_continuation(
0588       iterator_connect_op<Protocol, Executor, Iterator,
0589         ConnectCondition, IteratorConnectHandler>* this_handler)
0590   {
0591     return boost_asio_handler_cont_helpers::is_continuation(
0592         this_handler->handler_);
0593   }
0594 
0595   template <typename Protocol, typename Executor>
0596   class initiate_async_iterator_connect
0597   {
0598   public:
0599     typedef Executor executor_type;
0600 
0601     explicit initiate_async_iterator_connect(
0602         basic_socket<Protocol, Executor>& s)
0603       : socket_(s)
0604     {
0605     }
0606 
0607     executor_type get_executor() const noexcept
0608     {
0609       return socket_.get_executor();
0610     }
0611 
0612     template <typename IteratorConnectHandler,
0613         typename Iterator, typename ConnectCondition>
0614     void operator()(IteratorConnectHandler&& handler,
0615         Iterator begin, Iterator end,
0616         const ConnectCondition& connect_condition) const
0617     {
0618       // If you get an error on the following line it means that your
0619       // handler does not meet the documented type requirements for an
0620       // IteratorConnectHandler.
0621       BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
0622           IteratorConnectHandler, handler, Iterator) type_check;
0623 
0624       non_const_lvalue<IteratorConnectHandler> handler2(handler);
0625       iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
0626         decay_t<IteratorConnectHandler>>(socket_, begin, end,
0627           connect_condition, handler2.value)(boost::system::error_code(), 1);
0628     }
0629 
0630   private:
0631     basic_socket<Protocol, Executor>& socket_;
0632   };
0633 } // namespace detail
0634 
0635 #if !defined(GENERATING_DOCUMENTATION)
0636 
0637 template <template <typename, typename> class Associator,
0638     typename Protocol, typename Executor, typename EndpointSequence,
0639     typename ConnectCondition, typename RangeConnectHandler,
0640     typename DefaultCandidate>
0641 struct associator<Associator,
0642     detail::range_connect_op<Protocol, Executor,
0643       EndpointSequence, ConnectCondition, RangeConnectHandler>,
0644     DefaultCandidate>
0645   : Associator<RangeConnectHandler, DefaultCandidate>
0646 {
0647   static typename Associator<RangeConnectHandler, DefaultCandidate>::type get(
0648       const detail::range_connect_op<Protocol, Executor, EndpointSequence,
0649         ConnectCondition, RangeConnectHandler>& h) noexcept
0650   {
0651     return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_);
0652   }
0653 
0654   static auto get(
0655       const detail::range_connect_op<Protocol, Executor,
0656         EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
0657       const DefaultCandidate& c) noexcept
0658     -> decltype(
0659       Associator<RangeConnectHandler, DefaultCandidate>::get(
0660         h.handler_, c))
0661   {
0662     return Associator<RangeConnectHandler, DefaultCandidate>::get(
0663         h.handler_, c);
0664   }
0665 };
0666 
0667 template <template <typename, typename> class Associator,
0668     typename Protocol, typename Executor, typename Iterator,
0669     typename ConnectCondition, typename IteratorConnectHandler,
0670     typename DefaultCandidate>
0671 struct associator<Associator,
0672     detail::iterator_connect_op<Protocol, Executor,
0673       Iterator, ConnectCondition, IteratorConnectHandler>,
0674     DefaultCandidate>
0675   : Associator<IteratorConnectHandler, DefaultCandidate>
0676 {
0677   static typename Associator<IteratorConnectHandler, DefaultCandidate>::type
0678   get(const detail::iterator_connect_op<Protocol, Executor, Iterator,
0679         ConnectCondition, IteratorConnectHandler>& h) noexcept
0680   {
0681     return Associator<IteratorConnectHandler, DefaultCandidate>::get(
0682         h.handler_);
0683   }
0684 
0685   static auto get(
0686       const detail::iterator_connect_op<Protocol, Executor,
0687         Iterator, ConnectCondition, IteratorConnectHandler>& h,
0688       const DefaultCandidate& c) noexcept
0689     -> decltype(
0690       Associator<IteratorConnectHandler, DefaultCandidate>::get(
0691         h.handler_, c))
0692   {
0693     return Associator<IteratorConnectHandler, DefaultCandidate>::get(
0694         h.handler_, c);
0695   }
0696 };
0697 
0698 #endif // !defined(GENERATING_DOCUMENTATION)
0699 
0700 } // namespace asio
0701 } // namespace boost
0702 
0703 #include <boost/asio/detail/pop_options.hpp>
0704 
0705 #endif // BOOST_ASIO_IMPL_CONNECT_HPP