C++ 模板参数推导/替换失败,当使用 std::function 和 std::bind 时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15542530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:27:59  来源:igfitidea点击:

template argument deduction/substitution failed, when using std::function and std::bind

c++functiontemplatesbind

提问by haipeng31

I have a compile error when using std::function in a templated member function, the following code is a simple example:

在模板化成员函数中使用 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;
}

And come with the following compile error:

并出现以下编译错误:

testtemplate.cpp: In function ‘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: candidate is: testtemplate.cpp:10:7: note: template void Test::setCallback(std::function)

testtemplate.cpp:10:7: note: template argument deduction/substitution failed:

testtemplate.cpp:29:92: note: ‘std::_Bind(TestA*, std::_Placeholder<1>, std::_Placeholder<2>)>' is not derived from ‘std::function'

testtemplate.cpp:在函数“int main()”中:

testtemplate.cpp:29:92: 错误:没有匹配的函数调用 'Test::setCallback(std::_Bind_helper)(int, int), TestA, const std::_Placeholder<1>&, const std::_Placeholder <2>&>::type)'

testtemplate.cpp:29:92: 注意: 候选是: testtemplate.cpp:10:7: 注意: 模板 void Test::setCallback(std::function)

testtemplate.cpp:10:7: 注意:模板参数推导/替换失败:

testtemplate.cpp:29:92:注意:'std::_Bind(TestA*, std::_Placeholder<1>, std::_Placeholder<2>)>' 不是从 'std::function' 派生的

I'm using C++11 and g++ 4.7

我正在使用 C++11 和 g++4.7

采纳答案by masoud

To figure out the problem let separate statements:

为了找出问题,让单独的语句:

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

setCallbackneeds to know type of Tand it can't deduce it from f, so give it a type

setCallback需要知道类型 ofT并且不能从 推断出来f,所以给它一个类型

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

回答by dspeyer

You can make type deduction work with some variant of:

您可以使用以下一些变体进行类型推导:

template<typename CALLBACK>
void setCallback(CALLBACK cb) {
  typedef CALLBACK::first_argument_type T;
  static_assert(is_same_type<CALLBACK,function<void(T,int)>>::value);
  ...
}

This way CALLBACK can be determined by looking at the argument. It might get into trouble if bind doesn't actually return a std::function but rather something that can be cast as one. I'm not sure.

这样 CALLBACK 就可以通过查看参数来确定。如果 bind 实际上不返回 std::function 而是可以将其转换为一个函数,则可能会遇到麻烦。我不知道。