我想创建一个模板函数来对通用函数和类成员函数进行排队。通过互联网搜索,我想出了以下代码,但编译时出错。
#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
答案 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++