【问题标题】:C++ How to bind and invoke a templated type methodC++ 如何绑定和调用模板化类型方法
【发布时间】:2017-06-08 21:06:06
【问题描述】:

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

这是我的代码示例:

#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;
}

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    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-&gt;DidSomething(x)。如果没有占位符,fnMethod 将不接受任何参数。

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

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

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

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

    【讨论】:

    • 谢谢!我喜欢 lambda,对我来说似乎更具描述性和清晰性。我会使用 mem_fn 但导致 C2893。 cppreference 示例 1 表明它需要实例,但我想我把它搞砸了 void DoOneThing(Outer&amp; outer, DidSomethingCallback fnDidSomething) { fnDidSomething(outer, 300); } 并用 inner.DoOneThing(*this, fnMem); 调用它
    • @ShoaevHares 对不起,你是对的,mem_fn 没有按照我说的那样做。将编辑。
    【解决方案2】:

    您以错误的方式使用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);
    

    应该是work

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多