【问题标题】:Binding functions with different signatures不同签名的绑定函数
【发布时间】:2014-04-30 13:56:20
【问题描述】:

如果有人问过这个问题,我深表歉意。

我以为你不能用不同的签名绑定函数,但是看看这个:

void TakesChar(char parameter)
{
    std::cout << parameter << std::endl;
}

using CallSig = void(float);
using CallBack = std::function<CallSig>;

int main()
{
    CallBack callback = std::bind(&TakesChar, std::placeholders::_1);
    callback(1.1f);
    callback(2.2f);

    return 0;
}

编译并运行。您可以尝试不同的参数类型和编号。例如,您可以修改 TakesChar 使其不带参数,并且仍然可以编译。

这是为什么?这背后有什么道理吗?我可以强制签名完全匹配吗?

谢谢。

【问题讨论】:

  • 我认为std::function的签名参数只涉及它自己的接口。只要转换后可以调用,封装的函数(对象)可以具有任何签名。此外,不可能从具有operator() 模板的函数对象中提取签名。在您的情况下,我认为 float 只是转换为 char
  • float 可转换为char。如果TakesChar 的参数是不存在从float 隐式转换的某种类型,则您的代码将无法编译。关于修改 TakesChar 使其不带任何参数的最后一部分只有在您还从 bind 调用中删除 _1 时才是正确的。您不能将占位符绑定到不存在的参数。如果你两者都做,那么你可以将任意数量的参数传递给生成的可调用对象。其原因在this answer 中进行了解释。
  • 谢谢,有道理。
  • typedefs 越少,代码的可读性就越高,尤其是像这样的简短问题。

标签: c++ c++11 callback


【解决方案1】:

其实这里有两个问题:

  1. 为什么允许转换?
  2. 为什么如果没有向bind 提供参数,返回对象会接受任意数量的参数?

前者只是对bind行为的决定:既然可以调用TakesChar(1.1f)为什么不让std::bind(&amp;TakesChar, _1)绑定到std::function&lt;void(float)&gt;呢?委员会决定允许。

如 cmets 中所述,后者已在 SO 上得到解决。简而言之,它不仅更容易,而且还允许bind 一个具有多个不同arities 的operator() 的对象。

【讨论】:

    猜你喜欢
    • 2011-05-11
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    相关资源
    最近更新 更多