Почему не удается привязать std:: bind и boost:: bind в этом руководстве Boost.Asio - программирование
Подтвердить что ты не робот

Почему не удается привязать std:: bind и boost:: bind в этом руководстве Boost.Asio

Я пробовал разные учебники в документации Boost.Asio и пытался заменить компоненты boost на С++ 11. Тем не менее, я получил ошибку, используя std:: bind в Timer.5 - Синхронизация обработчиков в многопоточных программах. Вот предлагаемый код:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer { /* Not relevent here */ };

int main()
{
  boost::asio::io_service io;
  printer p(io);
  boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
  io.run();
  t.join();

  return 0;
}

Я попытался заменить boost::thread на std::thread и boost::bind на std::bind. Вот мой код:

#include <functional>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer { /* Not relevent here */ };

int main() {
    boost::asio::io_service io;
    printer p(io);
    std::thread t(std::bind(&boost::asio::io_service::run, &io));
    io.run();
    t.join();
}

При компиляции с GCC 4.7 я получил эту ошибку времени компиляции:

g++ -std=c++0x main.cpp -lboost_system -lboost_date_time -lpthread
main.cpp: In function ‘int main()’:
main.cpp:52:60: erreur: no matching function for call to ‘bind(<unresolved overloaded function type>, boost::asio::io_service*)’
main.cpp:52:60: note: candidates are:
/usr/include/c++/4.6/functional:1444:5: note: template<class _Functor, class ... _ArgTypes> typename std::_Bind_helper::type std::bind(_Functor&&, _ArgTypes&& ...)
/usr/include/c++/4.6/functional:1471:5: note: template<class _Result, class _Functor, class ... _ArgTypes> typename std::_Bindres_helper::type std::bind(_Functor&&, _ArgTypes&& ...)

Откуда возникает эта ошибка, учитывая, что я не использовал никаких boost::asio::placeholders (как объяснение в этом вопросе stackoverflow Если std:: bind будет совместим с boost:: ASIO?)?

4b9b3361

Ответ 1

Функция члена boost::asio::io_service::run() перегружена: одна версия не принимает аргумента, а другая версия принимает один аргумент. То есть, для адреса адреса boost::asio::io_service::run требуется контекст, в котором компилятор может непосредственно вывести подпись функции. Тем не менее, std::bind() не требуется делать магию дедукции, в то время как кажется, что boost::bind() пытается найти подходящую перегрузку, т.е. Кажется, что ее первый тип аргумента легко сдерживается (предполагая, что пример boost действительно компилируется).

Обход этой проблемы позволяет явно указать тип первого аргумента std::bind() (он также должен работать с boost::bind()), например. например:

std::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io);

Я не проверял, выполняет ли стандарт какие-либо требования, но если он действительно не выполняет никаких требований, я бы рассмотрел реализацию, которая делает не перейти к героике, чтобы вывести тип аргумента из более высокого качества, хотя он делает меньше работы: он требует, чтобы пользователь записывал код, который может компилироваться без изменений на другом компиляторе.

Ответ 2

Просто помните, что в С++ 11 вы можете просто использовать лямбда, чтобы избежать всех неприятностей и значительно упростить все это. Старый:

boost::thread t(boost::bind(&boost::asio::io_service::run, &io));

или std:: version:

std::thread t(boost::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io_service));

стать справедливым:

std::thread t([&io_service](){io_service.run();});

Ответ 3

Это была огромная PITA, чтобы понять, так что спасибо Dietmar за подсказку. для тех, кто использует boost:: bind, ваше решение выглядит следующим образом:

// create the io_service    

boost::asio::io_service io_service;

 // assign some work to asio before starting
 {
    io_service.post(&some_work);   // just for example
    ....
 }

boost::thread t(boost::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io_service));

// work should be executed in a new thread

t.join()

return;

Ответ 4

Поскольку вы уже используете С++ 11: lambdas может быть альтернативой std:: bind для вас, например, std:: thread t (& io {io.run();});. Это полностью исключает разрешение перегрузки.

Чтобы получить правильный выход, решение (в asio standalone или boost:: asio):

asio::io_service io;
auto ptrToIoService = &io;
printer p(io);

//asio::thread t(std::bind(&asio::io_service::run, &io));
//asio::thread t([&io]() {io.run();});
asio::thread t([ptrToIoService] () { ptrToIoService->run();});

См. "Эффективный современный С++" в разделе "Пункт 31 Избегайте режимов захвата по умолчанию".