I decided to write my own awaitable in order to loader to learn how C++ coroutine works. For now, I want to build my own struct that is equivalent to this:
cppcoro::task<int> bar()
{
co_yield 42;
}
This is what I came up after reading CppReference's coroutine page. Which states Finally, awaiter.await_resume() is called, and its result is the result of the whole co_await expr expression. I assume that changing the return type of await_resume() is enough to gave both bar and make_awaitable the same functionality.
#include <iostream>
#include <coroutine>
#include <cppcoro/task.hpp>
#include <cppcoro/sync_wait.hpp>
auto make_awaitable() {
using return_type = int;
struct awaitable {
bool await_ready() {return false;}
void await_suspend(std::coroutine_handle<> h) {
std::cout << "In await_suspend()" << std::endl;
h.resume();
}
int await_resume() {return 42;};
};
return awaitable{};
}
cppcoro::task<int> foo()
{
int n = co_await make_awaitable();
std::cout << n << std::endl;
}
int main()
{
cppcoro::sync_wait(foo());
std::cout << "Called coro" << std::endl;
return 0;
}
But running the code generates an assertion error.
coro_test: /usr/include/cppcoro/task.hpp:187: cppcoro::detail::task_promise<T>::rvalue_type cppcoro::detail::task_promise<T>::result() && [with T = int; cppcoro::detail::task_promise<T>::rvalue_type = int]: Assertion `m_resultType == result_type::value' failed.
What am I doing wrong?
Compiler: GCC 10
The problem is, I think, that you declared your return type as task<int> but you don't actually co_return any int.
Does the problem go away if you co_return n?
Related
How would I exit a function with a return value without using return.
Is there something like this in c++ :
auto random_function() {
printf("Random string"); // Gets executed
exit_with_return_value(/* Any random value. */);
printf("Same string as before"); // Doesn't get executed
}
Because I'm aware about exit() which takes a exit code.
But is there any way I could exit with a return value.
It is just that I can't call return is parentheses like this:
( return /* random value*/ );
But I can call functions in parentheses,
(exit(0));
My use case:
template <typename ...Parameters>
class Parameter_Pack
{
private:
void* paramsAddr[sizeof...(Parameters)];
public:
Parameter_Pack(Parameters ...parameters) {
size_t count = 0;
((
parameters,
this->paramsAddr[count] = malloc(sizeof(Parameters)),
*(Parameters*)paramsAddr[count] = parameters,
count++
), ...);
}
auto operator[](size_t index) {
size_t count = 0;
try {
(((count == index ? : return *
(Parameters*)paramsAddr[index] : *
(Parameters*)paramsAddr[index]), count++), ...);
} catch (Parameters...) {
std::cout << "Error: " << std::endl;
}
}
const size_t size() const {
return sizeof...(Parameters);
}
};
The problem is I can't return in auto operator[](size_t index).
The compiler error is :
"expected primary-expression before 'return'"
This doesn't answer your question directly, but instead of reinventing the wheel why not unpack the parameter pack into an std::tuple. You can then use std::get to access the object's by index.
#include <iostream>
#include <tuple>
template<typename ...Args>
static void unpack(Args&& ...args)
{
std::tuple pack{ std::forward<Args>(args)... };
int first = std::get<0>(pack);
std::cout << first << '\n';
const std::string& second = std::get<1>(pack);
std::cout << second << '\n';
bool third = std::get<2>(pack);
std::cout << std::boolalpha << third << '\n';
}
int main()
{
unpack(42, std::string{ "Some string" }, false);
}
OK, so the only thing I could come up with that kind of does what you want is to use a std::vector in conjunction with a std::variant.
Personally I think this would be an annoying API to use but it will allow you to return multiple types from the subscript operator and doesn't require a constant expression, i.e. index can be a runtime value.
#include <iostream>
#include <variant>
#include <vector>
#include <string>
template<typename ...Args>
class Pack {
public:
using Types = std::variant<Args...>;
Pack(Args... args)
: pack_{ std::move(args)... }
{}
Types& operator[](const std::size_t index) {
return pack_.at(index);
}
std::size_t size() const noexcept {
return pack_.size();
}
private:
std::vector<Types> pack_;
};
int main() {
Pack pack{42, std::string{ "Some string" }, false};
std::cout << pack.size() << '\n';
if (int* num = std::get_if<int>(&pack[0])) {
std::cout << "My num: " << *num << '\n';
}
}
return is a statement. Statements can't be part of a larger expression, so you can't return as a subexpression of some larger expression.
throw is an expression. It can be a subexpression of a larger expression, and you can throw any object you like.
It will be inconvenient for your callers, particularly if you mix it with an ordinary return. It will also not match the expectations other programmers have for how functions work. For that reason, I suggest you don't throw when you mean return.
Consider the following simple coroutine, which tracks its construction and destruction:
#include <coroutine>
#include <iostream>
struct simple {
static inline int x = 0;
int id = 0;
simple() : id{ x++ } { std::cout << id << " constructed\n"; }
simple(simple&&) : id{ x++ } { std::cout << id << " move constructed\n"; }
~simple() { std::cout << id << " destructed\n"; }
struct promise_type {
simple get_return_object() { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
auto initial_suspend() noexcept { return std::suspend_never{}; }
auto final_suspend() noexcept { return std::suspend_never{}; }
};
};
simple f() { co_return; }
int main() {
f();
}
When compiling with GCC 10.1, the output is:
0 constructed
1 move constructed
1 destructed
—notably, id 0 is never destructed. This is true even with GCC trunk.
Is there something I've done wrong here, some hidden UB or the like? Or is GCC at fault here?
As a comparison, I tried using Clang's experimental coroutine support, and got
0 constructed
0 destructed
which is closer to what I was expecting. I also get this "correct" output even in GCC if I comment out the move constructor in the coroutine object.
Live example: https://godbolt.org/z/UQVURi
As Oliv mentioned, it appears this is just a bug with GCC's experimental coroutine support. A ticket has been raised here.
void F(void f(), void(*v)())
{
}
As far as I understand, the two parameters have the same type, both are a pointer to a function that takes nothing and returns void. What is these two ways of writing? If they are both the exact same thing, then why void f() is not popular as void(*f)()? The first one seems easier since it looks like how normal functions are written. Also what are all possible syntax someone can use when dealing with function pointers? Or where to find them? Here are some of the ones I was able to get:
#include <iostream>
#include <vector>
void func1()
{
std::cout << "func1\n";
}
void (*returnFunc1())()
{
return func1;
}
auto returnFunc1_2() -> void(*)()
{
return func1;
}
void func2(int x)
{
std::cout << "func2 " << x << "\n";
}
auto returnFunc2() -> void(*)(int)
{
return func2;
}
int func3(int, bool)
{
std::cout << "func3\n";
return 0;
}
int (*returnFunc3(long long))(int, bool)
{
return func3;
}
void func4(void f(), void(*v)())
{
std::cout << "func4\n";
}
void (*returnFunc4())(void(), void(*)())
{
return func4;
}
int main()
{
void (*funcPointer)() = func1;
funcPointer();
std::vector<void(*)()> v;
v.push_back(func1);
v.back()();
returnFunc2()(123);
returnFunc3(123)(456, true);
returnFunc4()(func1, func1);
}
Is there any other syntax that could be used? I'm just curious.
For example, what is the meaning of int (*(*foo)(void ))[3]? How to read such statements? Or where can I learn about reading such cryptic statements?
I'm working on a mechanism for creating "safe" callbacks, that won't cause undefined behavior when called after their parent object has been destroyed. The class should be generic enough to be able to wrap any callback, with void(...) callbacks simply being executed or not, depending on the status of the object that they are bound to, and callbacks that return a value returning a boost::optional with the returned value, if executed, or boost::none if not executed.The implementation is almost complete, but there are 2 things that make me worried that I don't fully understand my code...
If line 19 is uncommented and 18 commented out, the template won't compile - is this merely a syntactic problem that can be solved, or am I trying to use the result_of mechanism incorrectly (does the std::forward there change the semantics or is it superfluous?)
If line 88 is uncommented and 89 commented out, the compilation results in failure due to ambiguousness of the function call to fun, which I don't quite understand - it seems to me that fun(int&&) is an exact match, so why does the compiler complain of ambiguousness with fun(int) version?
If there are other subtle (or gross) errors, please comment as well.
Thanks.
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <memory>
#include <boost/optional.hpp>
template<class Func>
class SafeCallback
{
public:
SafeCallback(std::shared_ptr<bool> guard, const Func& callback)
: guard_(guard)
, callback_(callback)
{}
template<class... Args>
// auto operator()(Args&&... args) -> typename std::enable_if<std::is_void<typename std::result_of<Func(std::forward<Args>(args)...)>::type>::value, // won't compile with: 19:91: error: invalid use of template-name 'std::result_of' without an argument list
auto operator()(Args&&... args) -> typename std::enable_if<std::is_void<typename std::result_of<Func(Args...)>::type>::value,
void>::type
{
std::cout << "trying void callback" << std::endl;
if(guard_.lock())
{
std::cout << "callback is still alive :)" << std::endl;
callback_(std::forward<Args>(args)...);
return;
}
std::cout << "uh-oh, callback is dead!" << std::endl;
}
template<class... Args>
auto operator()(Args&&... args) -> typename std::enable_if<!std::is_void<typename std::result_of<Func(Args...)>::type>::value,
boost::optional<typename std::result_of<Func(Args...)>::type>>::type
{
std::cout << "trying non-void callback" << std::endl;
if(guard_.lock())
{
std::cout << "callback is still alive :)" << std::endl;
return callback_(std::forward<Args>(args)...);
}
std::cout << "uh-oh, callback is dead!" << std::endl;
return boost::none;
}
bool isAlive()
{
return guard_.lock();
}
private:
std::weak_ptr<bool> guard_;
Func callback_;
};
class SafeCallbackProvider
{
public:
SafeCallbackProvider()
: guard_(new bool(true))
{}
virtual ~SafeCallbackProvider() = default;
template<class Func>
SafeCallback<Func> makeSafeCallback(const Func& callback)
{
return SafeCallback<Func>(guard_, callback);
}
private:
std::shared_ptr<bool> guard_;
};
struct A : SafeCallbackProvider
{
void fun()
{
std::cout << "---this is fun---" << std::endl;
}
int fun(int&& i)
{
std::cout << "&& this is && " << i << " && fun &&" << std::endl;
return i;
}
// int fun(int i) // fails to compile with: 123:48: error: call of overloaded 'fun(int)' is ambiguous
int fun(int& i)
{
std::cout << "---this is ---" << i << "--- fun---" << std::endl;
return i;
}
};
int main()
{
A* a= new A;
auto cb = a->makeSafeCallback(
[&]()
{
a->fun();
});
cb();
delete a;
cb();
std::cout << "\n----------\n\n";
A* a2= new A;
auto cb2 = a2->makeSafeCallback(
[&](int i)
{
return a2->fun(i);
});
cb2(5);
delete a2;
cb2(5);
std::cout << "\n----------\n\n";
A* a3= new A;
auto cb3 = a3->makeSafeCallback(
[&](int&& i)
{
return a3->fun(std::forward<int>(i));
});
cb3(5);
delete a3;
cb3(5);
return 0;
}
Note: this only answers the first question, because I apparently have the attention span of a fly. More coming soon.
std::result_of essentially performs some magic based on a function type that looks like a function call. In the line that works:
typename std::result_of<Func(Args...)>::type
This is the intended use, simulating the call of an instance of Func with values of types Args.... On the other hand:
typename std::result_of<Func(std::forward<Args>(args)...)>::type
This expands Args and args into a group of values, which then form a chain of ,-operators inside a functoin-style cast to Func. The whole thing is an expression instead of the type std::result_of expects.
It looks like you're halfway to using decltype instead, which would look like:
decltype(std::declval<Func&>()(std::forward<Args>(args)...))
... or, if you can be bothered to move it underneath callback_'s declaration:
decltype(callback_(std::forward<Args>(args)...))
Rules of Overloading are that .
Signature of function should be different.
In both the case compiler is finding same signature, try to change the signature and see the result.
I have a function foo that returns a future. foo will register a callback which will be called after foo returns.
future<int> foo() {
promise<int> p;
future<int> ret(p.get_future());
thread(bind([] (promise<int> &&p) {
this_thread::sleep_for(chrono::seconds(3));
p.set_value(10);
}, move(p))).detach();
return move(ret);
}
int main()
{
auto f = foo();
cout << f.get() << endl;
return 0;
}
But it seems like that std::bind forwards the rvalue reference as a lvalue reference so that can not be successfully compiled. Is there any way to fix it?
I have to write an ugly class to move the promise object:
template<typename T>
class promise_forward {
promise<T> promise_;
public:
promise_forward(promise<T> &&p) :
promise_(move(p)) {}
promise_forward(promise_forward<T> &&other) :
promise_(move(other.promise_)) {}
operator promise<T> () {
return move(promise_);
}
};
future<int> foo() {
promise<int> p;
future<int> ret(p.get_future());
thread(bind([] (promise<int> &&p) {
this_thread::sleep_for(chrono::seconds(3));
p.set_value(10);
}, promise_forward<int>(move(p)))).detach();
return ret;
}
int main()
{
auto f = foo();
cout << f.get() << endl;
return 0;
}
You, basically, doesn't need std::bind here (well , I believe so =)).
Here is a quick draft of a simplest async task launcher. It almost same as yours, but, just a little more generic: it can accept any function objects and it is less intrusive: function objects doesn't know nothing about promises or threading at all.
There are may be mistakes (I'm quite sure they are). And, of course, it is far far away, from std::async implementation (which, generally, more than just thread launcher, but, ideally, have a huge thread management back-end).
#include <thread>
#include <future>
#include <iostream>
#include <chrono>
template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type> my_async(Function && f, Args && ... args)
{
typedef typename std::result_of<Function(Args...)>::type ret_type;
std::promise<ret_type> p;
auto fut = p.get_future();
// lambda in separate variable, just to improve readability
auto l = [](Function && f, Args && ... args, std::promise<ret_type> && p)
{
p.set_value(f(args...));
};
std::thread th(l, std::move(f), std::move(args...), std::move(p));
th.detach();
return std::move(fut);
}
int wannaRunAsync(int i)
{
return i;
};
int main()
{
auto fut = my_async(&wannaRunAsync, 42);
auto fut2 = my_async([](int i) -> int { return i; }, 42);
std::cout << fut.get() << std::endl;
std::cout << fut2.get() << std::endl;
std::cin.get();
return 0;
}
I was able to compile and run it with
g++-4.8 and
clang++ but with msvc 2012 and 2013 preview it doesn't even compiles (probably, due to errors).
I've not tested this code at all, so be careful =) Hope it helps.