【问题标题】:Cast unresolved template overloaded class member强制转换未解析的模板重载类成员
【发布时间】:2017-04-12 10:22:43
【问题描述】:

我有一个有两个重载成员的类。一个接受整数,另一个是模板函数,接受一个参数。

class MyClass
{
    public:
        void doSomething(int data){ std::cerr << data;}
        template <typename T> doSomething(T &&data){ std::cerr << data;}
};

我要绑定这个函数

MyClass myobject;
auto my_bind = std::bind(&MyClass::doSomething, &myobject, 2);
my_bind();

但这并不能编译,因为编译器无法推断出要调用的函数。

错误:没有匹配的函数调用'bind(未解析的重载函数类型,MyClass*,int)'

我知道我必须强制转换函数。

auto my_bind2 = std::bind(static_cast<void (MyClass::*)(int)>(&MyClass::doSomething), &myobject, 2);

现在它可以按预期编译和工作了。

但是如果我想将它与任何其他参数绑定以调用模板函数怎么办?这甚至可能吗?我找不到语法。

这不起作用:

auto my_bind3 = std::bind(static_cast<void (MyClass::*)(std::string)>(&MyClass::doSomething), &myobject, std::string("Hello"));

我想避免使用 lambda。我简化了 MCVE 的代码,但在实际代码中我应该使用成员指针。

感谢您的帮助

【问题讨论】:

  • “我想避免使用 lambdas。” - 你更喜欢硬方法?

标签: c++


【解决方案1】:

您应该简单地提供成员函数模板的相关实例化的地址

auto my_bind3 = std::bind(&MyClass::doSomething<std::string&>, &myobject, std::string("Hello"));
                                 //Note the reference here ^^

上述方法有效,因为std::bind 复制了它的参数,并且由于doSomething 成员函数模板通过转发引用获取它的参数,我们需要利用引用折叠。

虽然像下面的 sn-p 这样的东西会“绑定”,

auto my_bind3 = std::bind(&MyClass::doSomething<std::string>, &myobject, std::string("Hello"));
                    //Note the absence of a reference here ^^

当你最终调用my_bind3()时它会失败。

Demo


如果您可以使用 lambda,请使用它,因为完美的前移会发挥作用。

auto my_bind4 = [&myobject](){ myobject.doSomething(std::string("\nHullo")); };

【讨论】:

  • 嗯,这比我想象的要容易......所以即使函数需要引用,参数实际上是复制的吗?我不明白为什么第二个不起作用。
  • @dydil, std::bind 将始终将其参数存储复制到它返回的对象中。当您调用返回对象的operator(...) 时,已经存储的 参数随后被传递给bounded 函数。请注意,std::bind 不会改变有界函数的语义。 (当“有界”函数是另一个std::bind时有一个例外)
  • 第二个失败,因为该实例化将导致像void doSomthing(std::string&amp;&amp; data) 这样的函数。但是当您调用“std::bind 对象”时,它将按值传递存储的参数,它不会通过调用std::move(...) 将其转换为rvalue。这失败了,因为实例化需要rvalue。 ..~ ~ ~ ~ ~ ~ ~ ~ 另一方面,第一种情况有效,因为它将创建一个类似void doSomthing(std::string&amp;&amp;&amp; data)的函数,并且通过引用折叠规则,它变成了void doSomthing(std::string&amp; data)。这将与 std::bind 很好地配合使用
  • 感谢您非常清楚的解释。我希望扣除的参数是std::string 类型而不是右值引用,但它实际上是有道理的。
猜你喜欢
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多