I've tried std::enable_if
and requires
:
template <typename Ret>
struct promise_type {
auto get_return_object() {/*...*/}
auto initial_suspend() {/*...*/}
auto return_void()
-> std::enable_if_t<std::is_void_v<Ret>> {/*...*/}
auto return_value(Ret)
-> std::enable_if_t<!std::is_void_v<Ret>> {/*...*/}
void unhandled_exception() {/*...*/}
auto final_suspend() noexcept {/*...*/}
// Rest of promise_type's definition ...
};
In file included from src/TestSyncTask.cpp:1:
In file included from include/asyncxx/SyncTask.hpp:2:
In file included from /usr/local/lib/gcc/x86_64-pc-linux-gnu/15.0.1/../../../../include/c++/15.0.1/coroutine:48:
/usr/local/lib/gcc/x86_64-pc-linux-gnu/15.0.1/../../../../include/c++/15.0.1/type_traits:2837:44: error: no type named 'type' in 'std::enable_if<false>'; 'enable_if' cannot be used to disable this declaration
2837 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
| ^~~~~
include/asyncxx/SyncTask.hpp:12:36: note: in instantiation of template type alias 'enable_if_t' requested here
12 | auto return_void() -> std::enable_if_t<std::is_void_v<Ret>> {}
| ^
src/TestSyncTask.cpp:4:15: note: in instantiation of member class 'SyncTask<int>::promise_type' requested here
4 | SyncTask<int> async_main(const int argc, const char *const argv[]) {
| ^
1 error generated.
template <typename Ret>
struct promise_type {
auto get_return_object() {/*...*/}
auto initial_suspend() {/*...*/}
auto return_void() requires std::is_void_v<Ret> {/*...*/}
auto return_value(Ret) requires (!std::is_void_v<Ret>) {/*...*/}
void unhandled_exception() {/*...*/}
auto final_suspend() noexcept {/*...*/}
// Rest of promise_type's definition ...
};
src/TestSyncTask.cpp:4:15: error: the coroutine promise type 'promise_type' declares both 'return_value' and 'return_void'
4 | SyncTask<int> async_main(const int argc, const char *const argv[]) {
| ^
include/asyncxx/SyncTask.hpp:12:14: note: member 'return_void' first declared here
12 | auto return_void() requires std::is_void_v<Ret> {}
| ^
include/asyncxx/SyncTask.hpp:13:14: note: member 'return_value' first declared here
13 | auto return_value(Ret val) requires (!std::is_void_v<Ret>) {
| ^
1 error generated.
How can I fix this?
I've tried std::enable_if
and requires
:
template <typename Ret>
struct promise_type {
auto get_return_object() {/*...*/}
auto initial_suspend() {/*...*/}
auto return_void()
-> std::enable_if_t<std::is_void_v<Ret>> {/*...*/}
auto return_value(Ret)
-> std::enable_if_t<!std::is_void_v<Ret>> {/*...*/}
void unhandled_exception() {/*...*/}
auto final_suspend() noexcept {/*...*/}
// Rest of promise_type's definition ...
};
In file included from src/TestSyncTask.cpp:1:
In file included from include/asyncxx/SyncTask.hpp:2:
In file included from /usr/local/lib/gcc/x86_64-pc-linux-gnu/15.0.1/../../../../include/c++/15.0.1/coroutine:48:
/usr/local/lib/gcc/x86_64-pc-linux-gnu/15.0.1/../../../../include/c++/15.0.1/type_traits:2837:44: error: no type named 'type' in 'std::enable_if<false>'; 'enable_if' cannot be used to disable this declaration
2837 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
| ^~~~~
include/asyncxx/SyncTask.hpp:12:36: note: in instantiation of template type alias 'enable_if_t' requested here
12 | auto return_void() -> std::enable_if_t<std::is_void_v<Ret>> {}
| ^
src/TestSyncTask.cpp:4:15: note: in instantiation of member class 'SyncTask<int>::promise_type' requested here
4 | SyncTask<int> async_main(const int argc, const char *const argv[]) {
| ^
1 error generated.
template <typename Ret>
struct promise_type {
auto get_return_object() {/*...*/}
auto initial_suspend() {/*...*/}
auto return_void() requires std::is_void_v<Ret> {/*...*/}
auto return_value(Ret) requires (!std::is_void_v<Ret>) {/*...*/}
void unhandled_exception() {/*...*/}
auto final_suspend() noexcept {/*...*/}
// Rest of promise_type's definition ...
};
src/TestSyncTask.cpp:4:15: error: the coroutine promise type 'promise_type' declares both 'return_value' and 'return_void'
4 | SyncTask<int> async_main(const int argc, const char *const argv[]) {
| ^
include/asyncxx/SyncTask.hpp:12:14: note: member 'return_void' first declared here
12 | auto return_void() requires std::is_void_v<Ret> {}
| ^
include/asyncxx/SyncTask.hpp:13:14: note: member 'return_value' first declared here
13 | auto return_value(Ret val) requires (!std::is_void_v<Ret>) {
| ^
1 error generated.
How can I fix this?
Share Improve this question edited Mar 31 at 7:31 shynur asked Mar 31 at 7:10 shynurshynur 5122 silver badges11 bronze badges 3 |1 Answer
Reset to default 2As @Jarod42 said, specialize for void
instead:
template <typename Ret>
struct promise_type_base
{
auto get_return_object() {/*...*/}
auto initial_suspend() {/*...*/}
void unhandled_exception() {/*...*/}
auto final_suspend() noexcept {/*...*/}
};
template <typename Ret>
struct promise_type : promise_type_base<Ret>
{
Ret return_value(Ret) { "..."; }
};
template <>
struct promise_type<void> : promise_type_base<void>
{
void return_void() { "..."; }
};
So why doesn't it work? Even if you add a requires
expression, the code would still need to compile and be legal C++, and void
isn't a valid argument type.
#include <type_traits>
template <typename Ret>
struct promise_type {
void return_void() requires std::is_void_v<Ret> {/*...*/}
Ret return_value(Ret) requires (!std::is_void_v<Ret>) {/*...*/}
};
promise_type<void> pv;
Compiler output:
<source>:6:23: error: argument may not have 'void' type
Ret return_value(Ret) requires (!std::is_void_v<Ret>) {/*...*/}
^
<source>:9:20: note: in instantiation of template class 'promise_type<void>' requested here
promise_type<void> pv;
^
1 error generated.
Compiler returned: 1
void
instead? – Jarod42 Commented Mar 31 at 7:18return_void
andreturn_value
, even if only one of them has its constraints met---this is arguably a specification bug, but we'll have to live with it until someone writes a paper to fix it. – Brian Bi Commented Apr 1 at 0:13