【问题标题】:std::function in template function模板函数中的 std::function
【发布时间】:2013-09-04 05:58:43
【问题描述】:

我正在尝试编写一个模板函数,它可以接受函子作为参数并在之后调用它。程序如下:

#include <iostream>
#include <functional>
using namespace std;

template<typename R, typename... Args>
R call(function<R(Args...)> fun, Args... args)
{
    cout << "call@ " << __LINE__ <<endl;
    return fun(args...);
}

int main()
{
    cout << call(std::plus<int>(),1,2) <<endl;
    return 0;
}

G++ 抱怨:

g++ -c -Wall -std=c++0x -I../include a.cpp -o a.o
a.cpp: In function ‘int main()’:
a.cpp:16:38: error: no matching function for call to ‘call(std::plus<int>, int, int)’
a.cpp:16:38: note: candidate is:
a.cpp:7:3: note: template<class R, class ... Args> R call(std::function<_Res(_ArgTypes ...)>, Args ...)
a.cpp:7:3: note:   template argument deduction/substitution failed:
a.cpp:16:38: note:   ‘std::plus<int>’ is not derived from ‘std::function<_Res(_ArgTypes ...)>’
make: *** [a.o] Error 1

我想std::plus&lt;int&gt;() 可以推导出为std::function&lt;int(int,int)&gt;,但事实并非如此。那是为什么? GCC 是gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)

【问题讨论】:

    标签: c++ templates c++11 stl


    【解决方案1】:

    我想 std::plus() 可以推导出为 std::function

    没有。鉴于您传递了std::plus&lt;int&gt; 类型的对象,因此无法推断。

    在您的情况下,您不需要使用std::function,因为通常您在存储可以使用特定签名调用的不同函数/函数对象时主要使用它。

    这样,您可以让您的call 函数直接接受函数/函数对象,并推导出其原始类型,而无需使用std::function。此外,您可能还希望在接受参数时使用完美转发,并在将它们作为参数传递给函数/函数对象时使用 std::forward。您还应该使用函数的返回类型作为call 的返回类型。为此,请使用 C++11 的尾随返回类型和 decltype

    #include <iostream>
    #include <functional>
    using namespace std;
    
    template<typename R, typename... Args>
    auto call(R fun, Args&&... args) -> decltype(fun(std::forward<Args>(args)...))
    {
        cout << "call@ " << __LINE__ <<endl;
        return fun(std::forward<Args>(args)...);
    }
    
    int main()
    {
        cout << call(std::plus<int>(),1,2) <<endl;
        return 0;
    }
    

    LIVE CODE


    正如@Jan Hudec 所拥有的commented__LINE__ 一样,在所有对call 的调用中,无论传递什么函数,都会产生相同的结果。

    【讨论】:

    • +1 虽然你错过了 __LINE__ 的无用性。它将为 all 调用打印 same 行。
    • 我很想强调:“你不需要使用std::function”。 std::function 似乎被过度使用了。
    【解决方案2】:

    它不能推导出模板参数。

    我建议像这样更改函数签名:

    template<typename F, typename... Args>
    auto call(F fun, Args... args )
        -> decltype( fun(args...) )
    

    【讨论】:

      【解决方案3】:

      推导模板参数时不考虑大多数隐式转换。当然不是用户定义的。所以即使plus 可以转换为function,也没有什么区别。

      【讨论】:

        猜你喜欢
        • 2021-10-30
        • 2021-06-30
        • 1970-01-01
        • 1970-01-01
        • 2013-01-18
        • 1970-01-01
        • 2013-01-21
        • 1970-01-01
        相关资源
        最近更新 更多