C++ 如何绑定和调用模板化类型方法

C++ How to bind and invoke a templated type method

本文关键字:调用 方法 类型 何绑定 绑定 C++      更新时间:2023-10-16

>我正在尝试了解绑定到模板化类型方法的语法。这似乎与我的问题相似,但似乎没有给出绑定和调用模板化类型方法的示例。

这是我的代码示例:

#include <functional>
#include <iostream>
using namespace std;
void DidSomething(int x)
{
    cout << "Did something x = " << x << endl;
}
template <typename T>
class Outer
{
public:
    void StartSomething()
    {
        Inner inner;
        // below lines cause
        // error C2893 Failed to specialize function template
        //'unknown-type std::invoke(_Callable &&,_Types &&...)'
        auto fnGlobal = std::bind(&::DidSomething);
        inner.DoOneThing(fnGlobal);
        auto fnMethod = std::bind(&Outer<T>::DidSomething, this);
        inner.DoOneThing(fnMethod);
    }
    void DidSomething(int x)
    {
        cout << "Did something x = " << x << endl;
    }
    // example typedef, the actual callback has a lot of args (5 args)
    typedef std::function<void(int)> DidSomethingCallback;
private:
    class Inner
    {
    public:
        void DoOneThing(DidSomethingCallback fnDidSomething)
        {
            fnDidSomething(3);
        }
    };
    T t;
};
int main()
{
    Outer<bool> outer;
    outer.StartSomething();
    return 0;
}

>std::bind要求您为未绑定参数指定占位符,以便返回类型知道预期有多少参数以及将它们传递到何处。因此,您必须编写:

auto fnGlobal = std::bind(&::DidSomething, std::placeholders::_1);

告诉它fnGlobal接受一个参数,并且应该用该参数调用::DidSomething。否则,fnGlobal不会争论。同样

auto fnMethod = std::bind(&Outer<T>::DidSomething, this, std::placeholders::_1);

会让fnMethod接受一个参数,称之为x,然后调用this->DidSomething(x)。如果没有占位符,fnMethod将不会接受任何参数。

std::bind的笨重使得在许多情况下避免使用它是可取的。在第一种情况下,写就足够了

// the & is optional
auto fnGlobal = ::DidSomething;

使fnGlobal成为普通的函数指针。在第二种情况下,可以使用 lambda:

auto fnMethod = [this](int x) { DidSomething(x); };

你用错了std::bind。您需要传递相应数量的要绑定的参数或占位符,就像创建 std::bind 对象时一样。改变:

    auto fnGlobal = std::bind(&::DidSomething);
    inner.DoOneThing(fnGlobal);
    auto fnMethod = std::bind(&Outer<T>::DidSomething, this);
    inner.DoOneThing(fnMethod);

自:

    auto fnGlobal = std::bind(&::DidSomething, std::placeholders::_1);
    inner.DoOneThing(fnGlobal);
    auto fnMethod = std::bind(&Outer<T>::DidSomething, this, std::placeholders::_1);
    inner.DoOneThing(fnMethod);

那应该有效