带有可变参数 std::function 的 C++11 函数签名

标签 c++ c++11 variadic-templates

我正在尝试实现一个接受 std::function 的函数它返回一个 it 并可能获得任意数量的参数。

我已经尝试了以下方法,但它无法编译,而且我无法理解错误的含义。

template <typename ...Args>
void ThrowOnError(std::function<int(Args...)> func, Args... args)
{
    int err = func(args...);
    if (err < 0)
        throw std::exception();
}

int f()
{
    return 42;
}

int f(int x)
{
    return x;
}


int main()
{
    ThrowOnError(f);
    ThrowOnError(f, 1);
}

我尝试将模板化函数移动到 header ,但它没有用,如果我注释掉 f(int x) 也是如此功能,只留下调用 f , 我仍然得到 no matching overloaded function found'void ThrowOnError(std::function<int(Args...)>,Args...)': could not deduce template argument for 'std::function<int(Args...)>' from 'int (int)'

这里有什么问题?我在函数中缺少什么?

P.S - 我想要一个需要 std::function 的答案如果可能,不要为仿函数类型添加另一个类型名称。

最佳答案

您没有提供 std::function 作为参数,推论无法进行。
另一方面,要将函数分配给 std::function,您必须知道实际类型。要找到它,必须进行演绎。要进行推导,您应该首先将函数指针分配给 std::function,但后者的类型是未知的(因为推导尚未发生)。
如此循环。

此外,当您这样做时:

ThrowOnError(f);

编译器不可能知道你想使用什么f
你应该做这样的事情:

ThrowOnError(std::function<int()>{static_cast<int(*)()>(f)});

或者这个(如果你接受为仿函数使用另一个模板参数):

ThrowOnError(static_cast<int(*)()>(f));

这样您就可以明确地从重载集中选择正确的函数,而编译器不必猜测您的意图。
如前所述,如果您同意按如下方式修改 ThrowOnError 函数,则后者可以正常工作:

template <typename F, typename ...Args>
void ThrowOnError(F func, Args... args)
{
    int err = func(args...);
    if (err < 0)
        throw std::exception();
}

或者更好:

template <typename F, typename ...Args>
void ThrowOnError(F &&func, Args&&... args)
{
    int err = std::forward<F>(func)(std::forward<Args>(args)...);
    if (err < 0)
        throw std::exception();
}

关于带有可变参数 std::function 的 C++11 函数签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40334635/

相关文章:

用于对多个 True 或 False 测试进行评分的 C++ 程序

c++11 - 将 C++ 库放在全局命名空间之外

c++ - 绑定(bind)可变参数函数 C++

com - 通过使用具有有限可变参数的模板函数来限制允许的 COM 接口(interface) (std::is_same)

c++ - 带有 Xaml 应用程序的 Directx 工具包

c++ - 如何重新绑定(bind)自定义分配器?

c++ - 如何创建一个半透明的形状?

c++ - 在 Netbeans 中配置 C++11

c++ - 关于将变量传递给 STL 容器并且不丢失它们超出范围

c++ - 使用可变参数模板指定友元类