编译std :: functions的Queue的模板函数时出错

时间:2016-03-02 23:48:16

标签: c++

我想创建一个模板函数来对通用函数和类成员函数进行排队。通过互联网搜索,我想出了以下代码,但编译时出错。

#include <iostream>
#include <functional>
#include <queue>
#include <string>

double MyFunction(double num1, double num2)
{
    std::cout << "MyFunction( " << num1 << ", " << num2 << " )\n";
    return num1 + num2;
}

class MyClass
{
public:
    double MyClassFunction(double num1, double num2, double num3) const
    {
        std::cout << "MyClass::MyClassFunction( " << num1 << ", " << num2 << ", " << num3 << " )\n";
        return num1 + num2 + num3;
    }
};

struct MyFunctionQueue
{
    template <typename FUNC, typename... ARGS>
    void QueueFunction(FUNC fn, ARGS&&... args)
    {
        std::function<std::result_of_t<FUNC(ARGS...)> () > rFunc = std::bind(fn, args...);
        _myFQ.push(rFunc);
    }

    void Execute()
    {
        while (!_myFQ.empty())
        {
            _myR.push(_myFQ.front()());
            _myFQ.pop();
        }
    }

    double PopResult()
    {
        double r = _myR.front();
        _myR.pop();
        return r;
    }

    std::queue<std::function<double()>> _myFQ;
    std::queue<double> _myR;
};


int main()
{
    MyFunctionQueue funcQue;

    funcQue.QueueFunction(MyFunction, 1.234, 2.345);

    MyClass obj;
    funcQue.QueueFunction(&MyClass::MyClassFunction, std::ref(obj), 1.234, 2.345, 3.456);

    funcQue.Execute();

    std::cout << "MyFunction result: " << funcQue.PopResult() << std::endl;
    std::cout << "MyClass::MyClassFunction result: " << funcQue.PopResult() << std::endl;
}

我知道错误是在类成员函数上生成模板代码。由于我在使用模板方面知识有限,我无法弄清楚它有什么问题。任何人都可以帮助指出代码中的错误吗?我从VC ++得到的错误是:

1>------ Build started: Project: TestFunctionQueue, Configuration: Debug Win32 ------
1>  TestFunctionQueue.cpp
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): error C2672: 'std::invoke': no matching overloaded function found
1>  c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(31): note: see reference to class template instantiation 'std::result_of<FUNC (std::reference_wrapper<MyClass>,double,double,double)>' being compiled
1>          with
1>          [
1>              FUNC=double (__thiscall MyClass::* )(double,double,double) const
1>          ]
1>  c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(63): note: see reference to function template instantiation 'void MyFunctionQueue::QueueFunction<double(__thiscall MyClass::* )(double,double,double) const,std::reference_wrapper<MyClass>,double,double,double>(FUNC,std::reference_wrapper<MyClass> &&,double &&,double &&,double &&)' being compiled
1>          with
1>          [
1>              FUNC=double (__thiscall MyClass::* )(double,double,double) const
1>          ]
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): note: With the following template arguments:
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): note: '_Callable=double (__thiscall MyClass::* )(double,double,double) const'
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1469): note: '_Types={std::reference_wrapper<MyClass>, double, double, double}'
1>c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(31): error C2440: 'initializing': cannot convert from 'std::_Binder<std::_Unforced,FUNC &,std::reference_wrapper<MyClass> &,double &,double &,double &>' to 'std::function<unknown-type (void)>'
1>          with
1>          [
1>              FUNC=double (__thiscall MyClass::* )(double,double,double) const
1>          ]
1>  c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(31): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(32): error C2664: 'void std::queue<std::function<double (void)>,std::deque<_Ty,std::allocator<_Ty>>>::push(const std::function<double (void)> &)': cannot convert argument 1 from 'std::function<unknown-type (void)>' to 'std::function<double (void)> &&'
1>          with
1>          [
1>              _Ty=std::function<double (void)>
1>          ]
1>  c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(32): note: Reason: cannot convert from 'std::function<unknown-type (void)>' to 'std::function<double (void)>'
1>  c:\users\siu.chan\documents\visual studio 2015\projects\testfunctionqueue\testfunctionqueue\testfunctionqueue.cpp(32): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

1 个答案:

答案 0 :(得分:1)

所以,我认为这是vc ++的一个问题。当下一个参数是指针时,传递成员函数可以正常工作,但当它是引用时失败。

template <class F, class... A>
std::result_of_t<F(A...)> Foo::bar(F f, A... a)
{
    return 0;
}

Foo f;
f.bar(&Foo::other_function, std::ref(f)); //error
f.bar(&Foo::other_function, &f); //success

此外,当函数类型是函数(如result_of)时,vc ++中的void()失败,但clang和gcc都成功。

template <class F, class... A>
struct Foo
{
    typedef std::result_of_t<F(A...)> type;
};

Foo<int(int), int> //fails in only vc++