simon
simon

Reputation: 391

Error on compiling template function of Queue of std::functions

I want to make a template function to queue both general functions and also class member functions. With internet search, I came up with the following code but have error in compiling it.

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

I know the error is with the template code generation on the class member function. With my limited knowledge in using templates I cannot figure out what's wrong with it. Can anyone help to point out the mistake in the code? And the error I've got from VC++ is:

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

Upvotes: 1

Views: 612

Answers (1)

Weak to Enuma Elish
Weak to Enuma Elish

Reputation: 4637

So, I think this is an issue with vc++. Passing a member function works just fine when the next parameter is a pointer, but fails when it is a reference.

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

Additionally, result_of in vc++ fails when the function type is a function (like void()), but clang and gcc both succeed.

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

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

Upvotes: 1

Related Questions