-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[译]C++20: 协程一瞥 #31
Comments
函数的进化之路下面的代码样例一步一步地展示着函数的进化之路: // functionEvolution.cpp
int func1() {
return 1972;
}
int func2(int arg) {
return arg;
}
double func2(double arg) {
return arg;
}
template <typename T>
T func3(T arg) {
return arg;
}
struct FuncObject4 {
int operator()() { // (1)
return 1998;
}
};
auto func5 = [] {
return 2011;
};
auto func6 = [] (auto arg){
return arg;
};
int main() {
func1(); // 1972
func2(1998); // 1998
func2(1998.0); // 1998.0
func3(1998); // 1998
func3(1998.0); // 1998.0
FuncObject4 func4;
func4(); // 1998
func5(); // 2011
func6(2014); // 2014
func6(2014.0); // 2014
}
让我们迈向未来,看看特殊的协程:生成器。 |
生成器在传统C++中,我们可以实现一个贪婪的生成器(greedy generator)。 贪婪生成器下面的代码简单有效。函数getNumbers返回从begin到end的累加整数。begin小于end并且inc是正数。 // greedyGenerator.cpp
#include <iostream>
#include <vector>
std::vector<int> getNumbers(int begin, int end, int inc = 1) {
std::vector<int> numbers; // (1)
for (int i = begin; i < end; i += inc) {
numbers.push_back(i);
}
return numbers;
}
int main() {
std::cout << std::endl;
const auto numbers= getNumbers(-10, 11);
for (auto n: numbers) std::cout << n << " ";
std::cout << "\n\n";
for (auto n: getNumbers(0, 101, 5)) std::cout << n << " ";
std::cout << "\n\n";
} 当然,我也可以用算法std::iota重新造轮子,这样实现的getNumbers会更好。按下不表。 程序中两次输出是很有必要的。第一行的vector numbers可以得到所有值,尽管我只对这个拥有1000个元素的vector的前5个元素感兴趣。另外将这个函数转型成懒惰生成器十分简单。 懒惰生成器就这样: // lazyGenerator.cpp
#include <iostream>
#include <vector>
generator<int> generatorForNumbers(int begin, int inc = 1) {
for (int i = begin;; i += inc) {
co_yield i;
}
}
int main() {
std::cout << std::endl;
const auto numbers= generatorForNumbers(-10); // (2)
for (int i= 1; i <= 20; ++i) std::cout << numbers << " "; // (4)
std::cout << "\n\n";
for (auto n: generatorForNumbers(0, 5)) std::cout << n << " "; // (3)
std::cout << "\n\n";
} greedyGenerator.cpp的函数getNumbers返回了一个vector。lazyGenerator.cpp中的generatorForNumbers返回了一个生成器。 (3)处的表达式generatorForNumbers(0, 5) 仅仅是生成器的原地(in-place)用法。我想明确这一点,因为for循环没有终止条件,generatorForNumbers创造了一个无穷无尽的数据流。如果我仅仅想请求有限个数的值(像(4)处那样),那么无限的数据流没什么问题。而(3)处这种写法,表达式将永远运行下去! |
接下来是什么?我们并没有在C++20中获得完整的协程。但是我们得到了一个可以自己实现协程的框架,你可以假设对于这个话题,我将会有很多内容可以写。 以上为译文THE END |
译者注std::iota生成器: #include <iostream>
#include <numeric>
#include <vector>
void iota_test() {
std::vector<int> foo(10);
// 将从 0 开始的 10 次递增值赋值给 foo
std::iota(foo.begin(), foo.end(), 0);
// 输出 foo 中的内容
std::copy(foo.begin(),foo.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
int main() {
iota_test();
} 输出:
iota在头文件numeric中。并且这个不是C++11的,之前就有。 |
C++20提供了4大特性,刷新了我们对于现代C++编程的认知:概念(concepts)、范围库(the range library)、协程(coroutines)和模块(modules)。关于概念和范围库我已经写了一些博文。现在让我们来看一下协程:
我想用这张图来展开对于协程的深入讨论。
协程是这样一类函数,它能在运行期间挂起和恢复,并且能保存状态。C++中函数的进化步步深入。我在C++20中当成新知识来解读的这一特性其实是非常古老的概念。Melvin Conway发明了术语协程:coroutine。在1963年,在他关于编译器构造的出版物种首先引入了这一概念。Donald Knuth也成过程(procedures)是一种特殊的协程。
在C++20中,新关键字
co_await
和co_yield
给C++的函数扩充了两个新概念。在我展示一个生成器函数以彰显普通函数和协程的不同之前,我想先谈一谈函数的进化!
The text was updated successfully, but these errors were encountered: