asio icon indicating copy to clipboard operation
asio copied to clipboard

Compilation issue when upgrading boost 1.71 to 1.80 ( VS 2015 )

Open felipenava opened this issue 2 years ago • 9 comments

My environment:

Visual Studio 2015 Update 2 (Version 14.0.25123.00) I have the following compilation error when calling the boost::asio::post:

c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): error C2752: 'boost_asio_prefer_fn::call_traits<boost_asio_prefer_fn::impl,boost::asio::strand<boost::asio::io_context::executor_type>,void (const boost::asio::execution::detail::relationship::fork_t<0> &,boost::asio::execution::allocator_t<std::allocator<void>>),void,void,void,void,void,void,void>': more than one partial specialization matches the template argument list
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: could be 'boost_asio_prefer_fn::call_traits<Impl,T,void(P0,P1),enable_if<boost_asio_prefer_fn::call_traits<Impl,T,void(P0),void,void,void,void,void,void,void>::overload!=,void>::type,enable_if<boost_asio_prefer_fn::call_traits<Impl,call_traits<Impl,T,void(P0),void,void,void,void,void,void,void>::result_type,void(P1),void,void,void,void,void,void,void>::overload!=,void>::type,void,void,void,void,void>'
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: or       'boost_asio_prefer_fn::call_traits<Impl,T,void(P0,P1,PN...),enable_if<boost_asio_prefer_fn::call_traits<Impl,T,void(P0),void,void,void,void,void,void,void>::overload!=,void>::type,enable_if<boost_asio_prefer_fn::call_traits<Impl,call_traits<Impl,T,void(P0),void,void,void,void,void,void,void>::result_type,void(P1,PN...),void,void,void,void,void,void,void>::overload!=,void>::type,void,void,void,void,void>'
c:\local\boost_1_80_0\boost\asio\use_future.hpp(141): note: see reference to class template instantiation 'boost::asio::use_future_t<std::allocator<void>>::std_allocator_void' being compiled
c:\local\boost_1_80_0\boost\asio\use_future.hpp(150): note: see reference to class template instantiation 'boost::asio::use_future_t<std::allocator<void>>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\relationship.hpp(595): note: see reference to class template instantiation 'boost::asio::execution::detail::relationship_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\outstanding_work.hpp(597): note: see reference to class template instantiation 'boost::asio::execution::detail::outstanding_work_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\occupancy.hpp(163): note: see reference to class template instantiation 'boost::asio::execution::detail::occupancy_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\mapping.hpp(764): note: see reference to class template instantiation 'boost::asio::execution::detail::mapping_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\context.hpp(170): note: see reference to class template instantiation 'boost::asio::execution::detail::context_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\bulk_guarantee.hpp(852): note: see reference to class template instantiation 'boost::asio::execution::detail::bulk_guarantee_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\blocking_adaptation.hpp(787): note: see reference to class template instantiation 'boost::asio::execution::detail::blocking_adaptation_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\execution\blocking.hpp(998): note: see reference to class template instantiation 'boost::asio::execution::detail::blocking_t<0>' being compiled
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): error C2672: 'operator __surrogate_func': no matching overloaded function found
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): error C2893: Failed to specialize function template 'enable_if<boost_asio_prefer_fn::call_traits<boost_asio_prefer_fn::impl,T,void(P0,P1,PN...),void,void,void,void,void,void,void>::overload==,call_traits<boost_asio_prefer_fn::impl,T,void(P0,P1,PN...),void,void,void,void,void,void,void>::result_type>::type boost_asio_prefer_fn::impl::operator ()(T &&,P0 &&,P1 &&,PN &&...) noexcept(<expr>) const'
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: With the following template arguments:
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: 'T=boost::asio::strand<boost::asio::io_context::executor_type>'
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: 'P0=const boost::asio::execution::detail::relationship::fork_t<0> &'
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: 'P1=boost::asio::execution::allocator_t<std::allocator<void>>'
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(59): note: 'PN={}'
c:\local\boost_1_80_0\boost\asio\impl\post.hpp(61): error C2672: 'operator __surrogate_func': no matching overloaded function found

That's the way we call post:

boost::asio::post( m_strand, boost::bind( &DeferedCallMechanism::Run,
    this,
    task,
    nullptr,
    threadId,
    std::weak_ptr<std::promise>() ) );

I've been testing older versions of boost to identify when the problem started, so in version 1.71 the problem doesn't occur. So, the problem only occurred from version 1.73 -> 1.74 and so on.

I believe it is something in this change on standard executors, I've found it here, first item: https://www.boost.org/users/history/version_1_74_0.html

Another interesting point is that in visual studio 2015 update 3 the problem does not occur, only in update 2. As I can't update my version of the visual studio at the moment, do you know any way to solve this? a workaround would help.

Thanks in advance.

felipenava avatar Oct 13 '22 13:10 felipenava

Please format your code properly, this very hard to read.

What C++ standard are you compiling for?

Does

boost::asio::post( m_strand, boost::bind( &DeferedCallMechanism::Run,
    this,
    task,
    nullptr,
    threadId,
    std::weak_ptr<std::promise>() ) );

Work?

klemens-morgenstern avatar Oct 13 '22 16:10 klemens-morgenstern

Please format your code properly, this very hard to read.

What C++ standard are you compiling for?

Does

boost::asio::post( m_strand, boost::bind( &DeferedCallMechanism::Run,
    this,
    task,
    nullptr,
    threadId,
    std::weak_ptr<std::promise>() ) );

Work?

It doesn't work, only with update 3 ( VS 2015 ).

C++ standard: C++14 toolset: msvc-14.0

felipenava avatar Oct 13 '22 17:10 felipenava

What's the signature of DeferedCallMechanism::Run ?

klemens-morgenstern avatar Oct 14 '22 00:10 klemens-morgenstern

What's the signature of DeferedCallMechanism::Run ?

        void Run( const Tasks::ITask::Ptr& task,
                  ILeaderWrapper*          leaderWrapper,
                  const std::thread::id    postingThreadId,
                  std::weak_ptr<std::promise<void>> leaderPromoted );

felipenava avatar Oct 14 '22 06:10 felipenava

It does look like something is wrong with the bind expression, can you try using a lambda instead?

klemens-morgenstern avatar Oct 14 '22 06:10 klemens-morgenstern

It does look like something is wrong with the bind expression, can you try using a lambda instead?

Yes, I've tried it doesn't work, unfortunately. The error points me out to that implementation on boost\asio\impl\post.hpp

class initiate_post
{
public:
  template <typename CompletionHandler>
  void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
      typename enable_if<
        execution::is_executor<
          typename associated_executor<
            typename decay<CompletionHandler>::type
          >::type
        >::value
      >::type* = 0) const
  {
    typedef typename decay<CompletionHandler>::type handler_t;

    typename associated_executor<handler_t>::type ex(
        (get_associated_executor)(handler));

    typename associated_allocator<handler_t>::type alloc(
        (get_associated_allocator)(handler));

    execution::execute(
        boost::asio::prefer(
          boost::asio::require(ex, execution::blocking.never),
          execution::relationship.fork,
          execution::allocator(alloc)),
        BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
  }

  template <typename CompletionHandler>
  void operator()(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler,
      typename enable_if<
        !execution::is_executor<
          typename associated_executor<
            typename decay<CompletionHandler>::type
          >::type
        >::value
      >::type* = 0) const
  {
    typedef typename decay<CompletionHandler>::type handler_t;

    typename associated_executor<handler_t>::type ex(
        (get_associated_executor)(handler));

    typename associated_allocator<handler_t>::type alloc(
        (get_associated_allocator)(handler));

    ex.post(BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);
  }
};

felipenava avatar Oct 14 '22 09:10 felipenava

What does your lambda solution look like?

klemens-morgenstern avatar Oct 15 '22 08:10 klemens-morgenstern

What does your lambda solution look like?

        auto RunLambda = [ ]( const Tasks::ITask::Ptr& task,
                              ILeaderWrapper*          leaderWrapper,
                              const std::thread::id    postingThreadId,
                              std::weak_ptr<std::promise<void>> leaderPromoted )
        {};

        auto bind_handle = boost::bind<void>( RunLambda, task, nullptr, threadId, std::weak_ptr<std::promise<void>>( ) );
        auto bind_exc_handle = boost::asio::bind_executor( m_strand, bind_handle );
        boost::asio::post( bind_exc_handle );

felipenava avatar Oct 17 '22 10:10 felipenava

Why are you capturing Tasks::ITask::Ptr by reference, not by value?

klemens-morgenstern avatar Oct 17 '22 13:10 klemens-morgenstern