何も考えずに std::make_shared を std::bind するとエラーになります。

struct A {
    A(int) {};
};

int main()
{
    auto fn = std::bind(std::make_shared<A>, 1); // A::A() を呼ぼうとしてエラー
}

回避方法は make_shared のテンプレート引数 Args の部分に make_shared の引数の型を明示的に書くこと。

    auto fn = std::bind(std::make_shared<A, int>, 1); // A::A(int) を呼ぼうとしてOK

なんでこうなるのかというと、 std::make_shared<A>(1) と関数呼び出しで書いた場合はテンプレート引数 Args は引数から推論されるが、上のような使い方だと直接的な関数呼び出しではないので推論されず、Args は空、つまりデフォルトコンストラクタを呼ぶ make_shared になる、ということのようです。

一般化して、関数引数からテンプレート引数を推論するような関数テンプレートを std::bind する場合には注意が必要、ということになります。

Trackback

no comment untill now

Add your comment now