Почему тип сопрограммы должен быть перемещаемым?

[Это относится к сопрограммам TS, VC++17 и новее. Не дубликат ]

Я экспериментирую с экспериментальными сопрограммами. Я определил тип сопрограммы под названием "resumable_thing" (он основан на выступлении Макнеллиса в 2016 году. В настоящее время он превратился в примитивный одноклеточный генератор.) Этот тип не будет компилироваться, если только не будет создан конструктор копирования или move- Конструктор определен, несмотря на то, что ctor никогда не может быть вызван?

Это почему?

#include <iostream>
#include <experimental/coroutine>
#include <experimental/generator>

using namespace std;
using namespace experimental;
template<class T>
struct resumable_thing {
    struct promise_type {
        T _value;
        resumable_thing get_return_object() {
            return resumable_thing(coroutine_handle<promise_type>::from_promise(*this));
        }
        auto initial_suspend() { return suspend_always{}; }
        auto final_suspend() { return suspend_always{}; }
        void return_value(const T& value) {_value = value; }        
        void yield_value(const T&v) { return_value(v); }
    };

    coroutine_handle<promise_type> _coroutine;

    // ???? Why must I define this? ????
    resumable_thing(resumable_thing &&other) {
        assert(false);
        _coroutine = std::move(other._coroutine);
        other._coroutine = nullptr;
    }
    // Member functions 
    void resume() { _coroutine.resume(); }
    auto get() {return _coroutine.promise()._value;}
    auto operator() () { resume(); return get(); }

    // Ctors dtors
    resumable_thing(resumable_thing const&) = delete; 
    resumable_thing& operator=(resumable_thing const&) = delete;
    resumable_thing() = default;

    explicit resumable_thing(coroutine_handle<promise_type> coroutine)
        : _coroutine(coroutine)
    {}

    ~resumable_thing() { if (_coroutine) _coroutine.destroy(); }



};

static
resumable_thing<int> take_five() {
    for (int i = 0; i<5 ; ++i) {
        co_yield i;
    }
    co_return -1;
}

int main() {    
    auto count = take_five();
    for (int i = count(); i >= 0; i=count()) {
        cout << i << '\n';
    }
    return 0;
}

ДОБАВЛЕНО ПОЗЖЕ. Я до сих пор не знаю, почему VC++ жалуется. В любом случае, ясно, что должны делать грузчики, если они что-то делают, а именно:

resumable_thing(resumable_thing &&right_) 
    : coroutine_(right_.coroutine_)
{
    right_.coroutine_ = nullptr;
}

resumable_thing &operator=(resumable_thing &&right_)
{
    if (this != std::addressof(right_)) {
        coroutine_ = right_.coroutine_;
        right_.coroutine_= nullptr;
    }
    return *this;
}

0 ответов

Другие вопросы по тегам