1. ホーム
  2. c++

[解決済み】std::function と std::bind を使用した場合のテンプレート引数の推論/置換に失敗する。

2022-01-27 02:35:56

質問

テンプレート化されたメンバ関数でstd::functionを使用すると、コンパイルエラーが発生します。

#include <functional>
#include <memory>
using std::function;
using std::bind;
using std::shared_ptr;

class Test {
public:
     template <typename T>
     void setCallback(function<void (T, int)> cb); 
};

template <typename T>
void Test::setCallback(function<void (T, int)> cb)
{
    // do nothing
}

class TestA {
public:
    void testa(int a, int b) {   }
};


int main()
{
    TestA testA;
    Test test;
    test.setCallback(bind(&TestA::testa, &testA, std::placeholders::_1, std::placeholders::_2));
    return 0;
}

そして、以下のようなコンパイルエラーが発生します。

testtemplate.cpp: 関数 'int main()'内。

testtemplate.cpp:29:92: error: no matching function for call to 'Test::setCallback(std::_Bind_helper)(int, int), TestA, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type)' です。

testtemplate.cpp:29:92: note: 候補は: testtemplate.cpp:10:7: note: テンプレート void Test::setCallback(std::function)

testtemplate.cpp:10:7: note: テンプレート引数 の控除/置換に失敗しました。

testtemplate.cpp:29:92: note: 'std::_Bind(TestA*, std::_Placeholder<1>, std::_Placeholder<2>)>' は 'std::function' から派生したものではありません。

C++11とg++ 4.7を使用しています。

どのように解決するのですか?

問題を把握するために、ステートメントを分けてみましょう。

auto f = bind(&TestA::testa, &testA, _1, _2); // OK
test.setCallback(f);                          // <<--- Error is here

setCallback の種類を知る必要があります。 T から推測することはできません。 f ということで、この型に

test.setCallback<TYPE>(f); // TYPE: int, float, a class, ...