Почему C++ не может сказать, что return_void и return_value являются взаимоисключающими?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Почему C++ не может сказать, что return_void и return_value являются взаимоисключающими?

Сообщение Anonymous »

Я пытаюсь определить свой собственный тип обещания сопрограммы, и у меня есть следующие объявления:
void return_void() requires std::same_as {}

template
void return_value(X&& x) requires (!std::same_as) {}

Но компилятор жалуется, что я определил оба, несмотря на объявления require:
return.cpp: In function ‘Future b()’:
return.cpp:103:40: error: the coroutine promise type ‘std::__n4861::__coroutine_traits_impl::promise_type’ {aka ‘Future::promise_type’} declares both ‘return_value’ and ‘return_void’
103 | __attribute__((noinline)) Future b()
| ^
return.cpp:27:14: note: ‘return_void’ declared here
27 | void return_void() requires std::same_as {}
| ^~~~~~~~~~~
return.cpp:30:14: note: ‘return_value’ first declared here
30 | void return_value(X&& x) requires (!std::same_as) {}
| ^~~~~~~~~~~~

Разве смысл функции require не в том, чтобы иметь возможность выражать подобные перегрузки без трюков std::enable_if и выведенных типов?
Полный минимальный пример:
#include
#include
#include
#include
#include

template
class Future
{
public:
class Awaiter;

class promise_type {
private:
std::exception_ptr _exception;
std::coroutine_handle _continuation;

friend class Awaiter;

public:
Future get_return_object() { return {HandleT::from_promise(*this)}; }

std::suspend_always initial_suspend() { return {}; }

std::suspend_never final_suspend() noexcept { return {}; }

void return_void() requires std::same_as {}

template
void return_value(X&& x) requires (!std::same_as) {}

void unhandled_exception() {
_exception = std::current_exception();
}
};

operator bool() const
{
return _status == Status::Done || _status == Status::Exception;
}

struct Awaiter {
private:
Future& future;

public:
explicit Awaiter(Future& future)
: future(future)
{}

// this will check if the future is already done, e.g. if it
// was `co_await`ed previously
bool await_ready() const noexcept { return bool(future); }

// this coroutine is the one doing the `co_await`
std::coroutine_handle await_suspend(std::coroutine_handle handle) noexcept
{
// remember we want to resume back intot his caller later
future._handle.promise()._continuation = handle;

// For now let the coroutine associated with this future
// run, via "symmetric transfer", which takes the caller
// resume call off the stack and replaces it with this
// coroutine.
return future._handle;
}

void await_resume() const noexcept
{
}
};

auto operator co_await() {
return Awaiter(*this);
}

void resume() {
_handle.resume();
}

protected:
using HandleT = std::coroutine_handle;

Future(HandleT&& p)
: _handle(std::move(p))
{}

Future(const Future&) = delete;
Future& operator=(const Future&) = delete;

friend class Awaiter;

enum class Status {
Unfinished,
Done,
Exception,
Empty
} _status = Status::Unfinished;
HandleT _handle;
std::exception_ptr _exception = nullptr;
};

Future b()
{
co_return;
}


Подробнее здесь: https://stackoverflow.com/questions/793 ... -exclusive
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»