0

I am attempting implement packaged_task as a template class, using promises.

My compile error says that I am referencing a deleted function. I suspect I need to implement copy and/or move semantics, but I am confused how and where to begin. Any advice is much appreciated:

#include "stdafx.h"
#include <iostream>
#include <future>
#include <functional>
#include <thread>
using namespace std;

//Base case
template<class>
class promised_task;

//Templated class
template<class Ret, class...Args>
class promised_task<Ret(Args...)> {
public:
    //Constructor
    //Takes a function argument that is forwarded to fn member
    template<class F>
    explicit promised_task(F&& f) :fn(f){}

    //get_future member function:
    future<Ret> get_future(){
        return prom.get_future();
    }

    //Set value
    void operator()(Args&&...args){
        prom.set_value(fn(forward<Args>(args)...));
    }

private:
    //Promise member
    promise<Ret> prom;

    //Function member
    function<Ret(Args...)> fn;
};


//Sample function from cplusplus.com
int countdown(int from, int to){
    for (int i = from; i != to; --i){
        cout << i << endl;
        this_thread::sleep_for(chrono::seconds(1));
    }
    cout << "Lift off!" << endl;
    return from - to;
}

//Verification function also from cplusplus.com
int main(){
    promised_task<int(int, int)>tsk(countdown);
    future<int>ret = tsk.get_future();

    thread th(move(tsk), 10, 0);

    int value = ret.get();

    cout << "The countdown lasted for " << value << " seconds." << endl;

    th.join();

    cout << "Press any key to continue:" << endl;
    cin.ignore();
    return 0;
}
  • which compiler are you using? what is the exact error message? – m.s. May 04 '15 at 17:33
  • VS 2013 express: Error 1 error C2280: 'std::promise::promise(const std::promise &)' : attempting to reference a deleted function c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory 303 1 15.2.a – ice_planet_hoth_boss May 04 '15 at 17:49
  • 1
    note that packaged_task has one method you cannot implement via promises: ready at thread exit or some such. Second, note that MSVC2013 has broken rvalue reference support: it does not generate move constructors, period. You have to write them manually. It will generate copy constructors. Third, knowing what line(s) of your code are generating the error means we don't have to compile it ourselves (in our heads, or on a system). Compiler error messages *mean* things, and a casual interpretation isn't all that useful. Please include your compiler error messages, and comment your line numbers. – Yakk - Adam Nevraumont May 04 '15 at 18:05

1 Answers1

1
thread th(move(tsk), 10, 0)

I'd guess this is the line generating the error.

Add:

promised_task(promised_task&& o):
  prom(std::move(o).prom), fn(std::move(o).fn)
{}

to promised_task in order to manually write a move ctor. C++11 mandates that the compiler write the above move constructor (or one equivalent) for you. MSVC2013 is not a compliant C++11 compiler.

The error is complaining that it cannot move a promised_task via promised_task(promised_task const&), which is implicitly deleted as promise has no copy constructor. The compiler should write promised_task(promised_task&&), but it isn't a C++11 compiler (not really), so it doesn't, and you get an error about a missing copy constructor.

When you try to move a type, if it lacks a move operation, copy is implicitly called. If copy is deleted/impossible/inaccessible, you get an error about not being able to copy the type.

Note that MSVC2015 is fixing that flaw. The big remaining hole in the MSVC2015 implementation of C++11 is what Microsoft calls "expression SFINAE", and knock-on effects (library components that fail compliance because it needs it to implement it).

In a recent communication about C++11 compliance, they have said they plan to ship that in an update for end-consumers (not a beta) sometime in the MSVC2015 cycle, but not enable the blocked library features until the next major release (to avoid ODR violations).

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524