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

时间:2016-10-30 23:08:28

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

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

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

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

我尝试将模板化的函数移动到标题但是它不起作用,如果我注释掉f(int x)函数并且只留下f的调用,我仍然得到{{1 }和no matching overloaded function found

这是什么问题?我在功能中缺少什么?

P.S - 如果可能的话,我想要一个'void ThrowOnError(std::function<int(Args...)>,Args...)': could not deduce template argument for 'std::function<int(Args...)>' from 'int (int)'的答案,而不是为仿函数类型添加另一个类型名称。

1 个答案:

答案 0 :(得分:4)

您没有提供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();
}