首先,我想预测我的代码的内存使用情况,就像任何负责任的程序员应该做的那样。即使我没有像我一样决定使用placement new分配我的协程框架,这也适用(见下面的伪代码)。即使假设我改变了对所有协程进行布局更新的想法,因此我让编译器将我所有的协程分配在堆上,我仍然希望 C++ 语言告诉我我将吃掉多少堆那。
但是,IRL,我的目标是高可靠性和嵌入式环境。有可能甚至是一个堆,所以...
struct coroutine_return_type
{
struct promise_type
{
void *operator new(std::size_t sz, char *buf, std::size_t szbuf)
{
if (sz > szbuf)
throw std::bad_alloc{};
return buf;
}
void operator delete(void *)
{
}
// ...
};
// ...
};
coroutine_return_type my_coroutine(char *, std::size_t)
{
// The arguments, char * and std::size_t,
// have been fowrarded to promise_type::operator new
// but here in the coroutine body they aren't used again...
for ( …Run Code Online (Sandbox Code Playgroud) C++20 中概念的一个好处是,此功能允许并鼓励程序员指定(使用 C++ 语言本身)有关其接口的信息,而这些信息以前必须以自然语言(例如英语)存在于纯人类文档中。
例如,我有一个通用算法,我们称之为template<int N, template<int> class X> void foo(X<N>)。我foo()解决了数值领域的某个问题。我关于如何使用的简单英语文档foo()是这样说的:“foo()接受 class 的参数X<N>,foo 的用户必须实现该参数。该类X<N>有一个整数模板参数 N 描述它有多少行。该类X<N>提供了运算符 [] 来访问一行的元素。X<N>还提供了一个成员函数reduce(),除非N=1,在这种情况下,reduce没有意义,因为只有一行。
我该如何理解这一点?我的第一个方法是:
template<class T>
concept Fooable = requires(T x, int i) {
x[i];
}
Run Code Online (Sandbox Code Playgroud)
但这并没有正式化reduce() 的要求。
如果我只有一个(形式)概念,那么我不能在 require 表达式中包含 x.reduce() ,因为某些 Fooable 类(即那些 N=1 的类)没有也不能实现 reduce() 方法。
我希望我的需求表达式包含类似if constepxr(T::N > 1) x.reduce();但是if控制流语句而不是表达式的内容,因此不能出现在需求表达式中。
问题:如何使用 C++20 概念来形式化此契约?
C++20 标准在[coroutine.noop] 中定义了一个“noop 协程” 。它是什么?它与 body 为 的函数{ co_return; }有何不同?
更新
感谢您提供提案和标准的链接。从这些参考资料中总结一下,“noop 协程”是resume()(or operator()) 和destroy()方法没有副作用的协程。
但是,destroy()在总用户编写的协同程序(我想!)有一个副作用,即破坏了协同程序,并进一步呼吁协程处理方法,包括resume()和destroy()现在将是不确定的行为,这比没有副作用的行为不同。
总之,没有办法编写一个destroy()没有副作用的协程,只有库提供的noop协程才有这个属性,对吗?
(欢迎更新答案,以回应我的问题的更新。)