読者です 読者をやめる 読者になる 読者になる

にゃははー

はへらー

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読んでたら混乱し始めた...