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

问题描述 投票:0回答:3

我在模板化成员函数中使用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: 错误:没有匹配的调用函数 'Test::setCallback(std::_Bind_helper)(int, int), TestA, 常量 std::_Placeholder<1>&, 常量 std::_Placeholder<2>&>::type)’

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

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

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

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

c++ function templates bind
3个回答
17
投票

为了弄清楚问题让单独的陈述:

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, ...

1
投票

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

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

这种方式可以通过查看参数来确定 CALLBACK。如果 bind 实际上不返回 std::function 而是可以转换为一个的东西,它可能会遇到麻烦。我不确定。


0
投票

FWIW,我收到此错误消息的原因完全不同(并且此页面是谷歌的热门页面):我忘记为从父类继承的子类添加访问说明符。考虑

#include <vector>
#include <memory>

class Parent
{
public:
    explicit Parent(int* a) : ptr_(a) {}
    virtual ~Parent() = default;
protected:
    int* ptr_{nullptr};
};

class Child : Parent  // right here, I forgot to add `public`
{
public:
    explicit Child(int* a) : Parent(a) {}
    ~Child() override = default;
};

int main()
{
    int a = 3;
    std::vector<std::unique_ptr<Parent>> items;

    items.emplace_back(std::make_unique<Child>(&a));
}

因为

Child
是一个
class
,这个默认为
private
继承
,这意味着
Parent
ctor和dtor是
private
,导致IMOcryptic compiler vomit。一旦我将其更改为

class Child : public Parent

一切顺利

© www.soinside.com 2019 - 2024. All rights reserved.