2012-01-28 12 views
16

Boost.Asioのドキュメントでdifferentsチュートリアルを試していましたが、boostコンポーネントをC++ 11で置き換えようとしました。しかし、Timer.5 - Synchronising handlers in multithreaded programsのstd :: bindを使ってエラーが発生しました。私はstd::bindによってstd::threadboost::bindboost::threadを交換しようとしたこのBoost.Asioチュートリアルでstd :: bindとboost :: bindを同じ意味で使うことができない

#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::asio::placeholdersを使用していない考慮に入れて、

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&& ...) 

このエラーがから来ている:

#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でコンパイルし、私はこのコンパイル時のエラーを得た:ここに私のコードです(このスタックオーバーフローの質問Should std::bind be compatible with boost::asio?で説明)?

+0

可能重複:http://stackoverflow.com/questions/8924149/should-stdbind-be-compatible-with-boostasioを参照してください。 – mark

+6

既にC++ 11を使用しているので、lambdaは代替'std :: thread t([&io](){io.run();});'これはオーバーロードの解決を完全に避けます。 – mavam

答えて

34

boost::asio::io_service::run()メンバ関数がオーバーロードされています.1つのバージョンは引数をとりませんが、別のバージョンは1つの引数をとります。すなわち、boost::asio::io_service::runのアドレスを取ることは、コンパイラが関数の署名を直接推論できるコンテキストを必要とする。しかし、std::bind()は、控除マジックを行う必要はありませんが、boost::bind()は一致するオーバーロードを見つけようとしています。つまり、最初の引数の型が容易に制約されているようです(ブーストの例が実際にコンパイルされると仮定します)。

この問題を回避するには、最初の引数の型をstd::bind()に明示的に指定できます(boost::bind()でも動作するはずです)。このように:

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

私は標準がどの要件を作るかどうかをチェックしていないが、それは実際には任意の要件をしない場合、私はに引数の型を推測するために英雄に行かないの実装を検討しますより品質は良くなりますが、ユーザは別のコンパイラでそのままコンパイルできるコードを書く必要があります。

1

これは巨大なピタだったので、Dietmarのヒントに感謝します。ブースト::バインドを使用してそれらのために、あなたのソリューションは、次のようになります。C++ 11以降あなただけ使用することができますラムダで

// 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; 
11

だけで簡単にノートでは、すべてのfaffを回避し、大幅に全体を簡素化します。旧:

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

かのstd ::バージョン:

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();}); 
+2

これはずっと優れています! – UmNyobe

0

Since you're already using C++11: lambdas may be an alternative to std::bind for you, e.g., std::thread t(&io { io.run(); });. This avoid the overload resolution entirely.

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();}); 

「Item 31」の「Effective Modern C++」を参照してください。デフォルトのキャプチャモードを避ける。"

関連する問題