2016-03-02 93 views
1

我想製作一個模板函數來排列一般函數和類成員函數。隨着互聯網搜索,我想出了以下代碼,但在編譯時出錯。編譯std :: functions隊列模板函數時出錯

#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

這看起來不正確:'std :: result_of_t '。更像'decltype(std :: declval ()(args ...))''? –

+0

那攪得VC2015編譯器以及:-( – simon

+0

我想你也想通過指針傳遞對象,而非參考,使用帶'的std :: function'的成員函數的時候,我不知道這是否是問題,然後''result_of ''會給你'FUNC'作爲返回類型 –

回答

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()),但鐺和gcc都成功失敗。

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

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

其實一提的是,就像一個指針可接受http://en.cppreference.com/w/cpp/concept/Callable –

+0

@PreferenceBean真的嗎?我不確定,但我覺得它一定是因爲它解決了這個問題,這是一個奇怪的巧合, –

+0

'std :: function ()> rFunc'在VS2015中正常工作。我不知道你爲什麼建議亂碼。 – nshct