std::bindとboost::bindとboost::asio::placeholders
c++ - Should std::bind be compatible with boost::asio? - Stack Overflow
std::bindにboost::asio::placeholder::errorを渡すと死ぬ(そりゃそうだ) - 2冊の本を3等分
Boost.Asioのasyncハンドラには多くの場合、Boost.Bindとboost::asio::placeholdersを組み合わせると思うので問題ないですが、C++11のstd::bindと組み合わせる時には注意が必要です。
boost::asio::placeholdersは実際にはBoost.Bindのboost::argを使っているので、boost::bindからすればplaceholderとして認識できるのは当然ですが、std::bindからしてみればboost::argはplaceholderではないので、そのままではstd::bindをAsioのhanlderにはできません。
これは、std::is_placeholderを特殊化することで対応出来ます。
user-defined typeのpartial specializationなので問題ない...はずです...*1。
#include <functional> #include <boost/bind/arg.hpp> namespace std { template <int n> struct is_placeholder<boost::arg<n>> : public ::std::integral_constant<int, n> { }; } // namespace std
最近の一般的なコンパイラであれば、上の定義で問題なくBoost.Bindのplaceholderをstd::bindに叩き込めます。
が、Boost.Bindのplaceholderにはもう一つのworkaround用定義があり、あろうことかBoost.Asioはデフォルトでこちらを使います。
これを考慮すると、
#include <functional> #include <boost/bind/arg.hpp> namespace std { template <int n> struct is_placeholder<boost::arg<n>> : public ::std::integral_constant<int, n> { }; template <int n> struct is_placeholder<boost::arg<n>(*)()> : public ::std::integral_constant<int, n> { }; } // namespace std
となります。
Boost.Asioだけでいいなら下の定義だけあればstd::bindを使うことができます。
# どうでもいいけど、はてぶろ未だにトラバ送れないのかな...
*1:n3337 17.6.4.2.1読んでたら混乱し始めた...