C ++ 23: Rang iyileştirmeleri ve std :: jeneratör
C ++ 20 somut bir kredin değil, bunları uygulamak için bir çerçeve sunar. Bu C ++ 23 ile değişir. std::generator İlk çimento koreroutin.
Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
std::generator C ++ 23'teki Gamme Kütüphanesi'nin genişlemesinin bir parçasıdır. Bu nedenle, bu makaleye C ++ 20'deki Ranges kütüphanesi ve C ++ 23'teki genişlemesi ile başlamak istiyorum. Ancak kısa bir süre alacağım. Zaten C ++ 20'deki aralıklar aralığında yazdım ve C ++ 23'teki genişlemesi:
Tamamlamak istediğim tek bir hikaye var:
Pitonlar range C ++ 23'te işlev
“Ranges Kütüphanesi ile Pythonic: Range and Filtre” ve “Pythons Range Fonksiyonu” Makalelerimde “İkinci” range-Python 2 işlevi aralıklar kütüphanesi ile uygulanır. Python-2 ve Python 3- arasındaki fark range-İşlev, 2 saater istekli bir sürümün, ancak 3 serisinin sürümünün tembel olmasıdır. Bu, 2 sürümünün sayı oluşturduğu anlamına gelirken, 3 serisinin sürümü istek üzerine numara üreten bir jeneratör döndürür. Eric Niebler'in V3 kütüphanesini kullanarak sorunu sadece C ++ 20'de çözebildim. Özellikle işleve ihtiyacım vardı stride(N)başka bir vizyonla ve her seferinde geliştirildi N-Delement iade.
std::ranges::views::stride C ++ 23 ve GCC derleyicilerinin bir parçasıdır ve MSVC sizi destekler. Bu örnekte pratik işlevi de kullanıyorum std::ranges::to. Bu C ++ 23 fonksiyonu ile kaplar ve dizeler alanlar tarafından oluşturulabilir. Şimdiye kadar, bu işlev sadece MSVC ve CLANG derleyicileri tarafından desteklenmiştir.
İşte pitonlar range-C ++ işlevi:
// rangeCpp23.cpp
#include <iostream>
#include <ranges>
#include <vector>
std::vector<int> range(int begin, int end, int stepsize = 1) {
std::vector<int> result{};
if (begin < end) { // (5)
auto boundary = [end](int i){ return i < end; };
result = std::ranges::views::iota(begin)
| std::views::stride(stepsize)
| std::views::take_while(boundary)
| std::ranges::to<std::vector>();
}
else { // (6)
begin++;
end++;
stepsize *= -1;
auto boundary = [begin](int i){ return i < begin; };
result = std::ranges::views::iota(end)
| std::views::take_while(boundary)
| std::views::reverse
| std::views::stride(stepsize)
| std::ranges::to<std::vector>();
}
return result;
}
int main() {
std::cout << std::endl;
// range(1, 50) // (1)
auto res = range(1, 50);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
// range(1, 50, 5) // (2)
res = range(1, 50, 5);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
// range(50, 10, -1) // (3)
res = range(50, 10, -1);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
// range(50, 10, -5) // (4)
res = range(50, 10, -5);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
}
MSVC derleyici çıkışına bakarsanız (1) – (4) 'deki görüntüler okumak için yeterince kolay olmalıdır:
Kurs çağrısının ilk iki konusu, oluşturulan sayıların başlangıcına ve sonuna dayanmaktadır. Başlangıç dahildir, ancak son değil. Üçüncü bir parametre olarak geçişin genişliği 1'dir. Aralık [begin, end] Aşağı iner, adımın genişliği negatif olmalıdır. Aksi takdirde boş bir liste veya boşluk elde edersiniz std::vector<int>.
Eğer durum (begin < end) ranges-(1) 'deki işlev okumak için yeterince kolay olmalıdır: begin başlangıç (std::views::iota(begin)), her öğeyi al n-te (std::views::stride(stepsize)) ve sınır koşulu uygulandığı sürece yapın (std::views::take_while(boundary)). Sonunda onu yaratıyorum std::vector<int>. İçinde else-Fall (2) Küçük bir numara kullanıyorum: Sayıları oluşturuyorum [end++, begin++[, nehme sie, bis die Randbedingung erfüllt ist, drehe sie um (std::views::reverse) und nehme jedes n-te Element.
Nun möchte ich mich den Koroutinen widmen.
std::generator
std::generator in C++23 ist die erste konkrete Koroutine. Ein std::generator erzeugt eine Folge von Elementen, in dem die Koroutine dort ihren Kontrollfluss wieder aufnimmt, wo sie pausiert hat.
// generator.cpp
#include <generator>
#include <ranges>
#include <iostream>
std::generator<int> fib() {
co_yield 0; // (1)
auto a = 0;
auto b = 1;
for(auto n : std::views::iota(0)) {
auto next = a + b;
a = b;
b = next;
co_yield next; // (2)
}
}
int main() {
for (auto f : fib() | std::views::take(10)) {
std::cout << f << " ";
}
}
Die Funktion fib ist eine Koroutine. Diese Koroutine erzeugt einen unendlichen Strom von Fibonacci-Zahlen. Der Zahlenstrom beginnt mit 0 (1) und wird mit der nächsten Fibonacci-Zahl fortgesetzt (2). Die Range-based for-Schleife fordert explizit die ersten 10 Fibonacci-Zahlen an.
Bislang unterstützt kein Compiler std::generator. Es lässt sich die Koroutinen-Natur von std::generator schön an seinem Header studieren:
std::ranges::elements_of kommt ins Spiel, wenn ein Generator rekursiv aufgerufen werden soll.
std::generator<int> fib() {
co_yield 0;
auto a = 0;
auto b = 1;
for(auto n : std::views::iota(0)) {
auto next = a + b;
a = b;
b = next;
co_yield next;
}
}
std::generator<int> outer() {
yield fib(); // (1)
yield std::ranges::elements_of(fib); // (2)
}
Der äußere Generator gibt in Zeile (1) den inneren std::generator<int> zurück, aber in Zeile (2) die Werte des inneren Generators. Beide Koroutinen besitzen den gleichen Rückgabetyp.
std::bind_back
Entsprechend zu std::bind_front in C++20 unterstützt C++23 std::bind_back. Das folgende Programm bindFrontBack.cpp zeigt die Anwendung der beiden Funktionen.
// bindFrontBack.cpp
#include <functional>
#include <iostream>
#include <string>
int main() {
std::cout << 'n';
auto add = [](Std :: String a, std :: String B, std :: String C) {dönüş a + b + c; }; Araba iki_three = std :: bind_front (ekle, "bir"); Std :: cout code>
Çıktı sayesinde program açıklanmalıdır.
Kısmi işlev uygulamaları hakkında daha fazla bilgi std::bind, std::bind_front VE std::bind_back "Yazılım Geliştirme Teknikleri: Kısmi Fonksiyon Uygulaması" makalemde mümkündür.
Sırada ne var?
Şimdi C ++ 23 ile bitirdim. Bu yüzden altı yıl geri dönmek istiyorum. Bir sonraki makalemde C ++ 17: Allocaters Polimorfik'te neredeyse bilinmeyen bir işlev hakkında yazacağım.
(RME)
C ++ 23: Rang iyileştirmeleri ve std :: jeneratör
C ++ 20 somut bir kredin değil, bunları uygulamak için bir çerçeve sunar. Bu C ++ 23 ile değişir. std::generator İlk çimento koreroutin.

Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.

std::generator C ++ 23'teki Gamme Kütüphanesi'nin genişlemesinin bir parçasıdır. Bu nedenle, bu makaleye C ++ 20'deki Ranges kütüphanesi ve C ++ 23'teki genişlemesi ile başlamak istiyorum. Ancak kısa bir süre alacağım. Zaten C ++ 20'deki aralıklar aralığında yazdım ve C ++ 23'teki genişlemesi:
Tamamlamak istediğim tek bir hikaye var:
Pitonlar range C ++ 23'te işlev
“Ranges Kütüphanesi ile Pythonic: Range and Filtre” ve “Pythons Range Fonksiyonu” Makalelerimde “İkinci” range-Python 2 işlevi aralıklar kütüphanesi ile uygulanır. Python-2 ve Python 3- arasındaki fark range-İşlev, 2 saater istekli bir sürümün, ancak 3 serisinin sürümünün tembel olmasıdır. Bu, 2 sürümünün sayı oluşturduğu anlamına gelirken, 3 serisinin sürümü istek üzerine numara üreten bir jeneratör döndürür. Eric Niebler'in V3 kütüphanesini kullanarak sorunu sadece C ++ 20'de çözebildim. Özellikle işleve ihtiyacım vardı stride(N)başka bir vizyonla ve her seferinde geliştirildi N-Delement iade.
std::ranges::views::stride C ++ 23 ve GCC derleyicilerinin bir parçasıdır ve MSVC sizi destekler. Bu örnekte pratik işlevi de kullanıyorum std::ranges::to. Bu C ++ 23 fonksiyonu ile kaplar ve dizeler alanlar tarafından oluşturulabilir. Şimdiye kadar, bu işlev sadece MSVC ve CLANG derleyicileri tarafından desteklenmiştir.
İşte pitonlar range-C ++ işlevi:
// rangeCpp23.cpp
#include <iostream>
#include <ranges>
#include <vector>
std::vector<int> range(int begin, int end, int stepsize = 1) {
std::vector<int> result{};
if (begin < end) { // (5)
auto boundary = [end](int i){ return i < end; };
result = std::ranges::views::iota(begin)
| std::views::stride(stepsize)
| std::views::take_while(boundary)
| std::ranges::to<std::vector>();
}
else { // (6)
begin++;
end++;
stepsize *= -1;
auto boundary = [begin](int i){ return i < begin; };
result = std::ranges::views::iota(end)
| std::views::take_while(boundary)
| std::views::reverse
| std::views::stride(stepsize)
| std::ranges::to<std::vector>();
}
return result;
}
int main() {
std::cout << std::endl;
// range(1, 50) // (1)
auto res = range(1, 50);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
// range(1, 50, 5) // (2)
res = range(1, 50, 5);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
// range(50, 10, -1) // (3)
res = range(50, 10, -1);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
// range(50, 10, -5) // (4)
res = range(50, 10, -5);
for (auto i: res) std::cout << i << " ";
std::cout << "nn";
}
MSVC derleyici çıkışına bakarsanız (1) – (4) 'deki görüntüler okumak için yeterince kolay olmalıdır:

Kurs çağrısının ilk iki konusu, oluşturulan sayıların başlangıcına ve sonuna dayanmaktadır. Başlangıç dahildir, ancak son değil. Üçüncü bir parametre olarak geçişin genişliği 1'dir. Aralık [begin, end] Aşağı iner, adımın genişliği negatif olmalıdır. Aksi takdirde boş bir liste veya boşluk elde edersiniz std::vector<int>.
Eğer durum (begin < end) ranges-(1) 'deki işlev okumak için yeterince kolay olmalıdır: begin başlangıç (std::views::iota(begin)), her öğeyi al n-te (std::views::stride(stepsize)) ve sınır koşulu uygulandığı sürece yapın (std::views::take_while(boundary)). Sonunda onu yaratıyorum std::vector<int>. İçinde else-Fall (2) Küçük bir numara kullanıyorum: Sayıları oluşturuyorum [end++, begin++[, nehme sie, bis die Randbedingung erfüllt ist, drehe sie um (std::views::reverse) und nehme jedes n-te Element.
Nun möchte ich mich den Koroutinen widmen.
std::generator
std::generator in C++23 ist die erste konkrete Koroutine. Ein std::generator erzeugt eine Folge von Elementen, in dem die Koroutine dort ihren Kontrollfluss wieder aufnimmt, wo sie pausiert hat.
// generator.cpp
#include <generator>
#include <ranges>
#include <iostream>
std::generator<int> fib() {
co_yield 0; // (1)
auto a = 0;
auto b = 1;
for(auto n : std::views::iota(0)) {
auto next = a + b;
a = b;
b = next;
co_yield next; // (2)
}
}
int main() {
for (auto f : fib() | std::views::take(10)) {
std::cout << f << " ";
}
}
Die Funktion fib ist eine Koroutine. Diese Koroutine erzeugt einen unendlichen Strom von Fibonacci-Zahlen. Der Zahlenstrom beginnt mit 0 (1) und wird mit der nächsten Fibonacci-Zahl fortgesetzt (2). Die Range-based for-Schleife fordert explizit die ersten 10 Fibonacci-Zahlen an.
Bislang unterstützt kein Compiler std::generator. Es lässt sich die Koroutinen-Natur von std::generator schön an seinem Header studieren:
std::ranges::elements_of kommt ins Spiel, wenn ein Generator rekursiv aufgerufen werden soll.
std::generator<int> fib() {
co_yield 0;
auto a = 0;
auto b = 1;
for(auto n : std::views::iota(0)) {
auto next = a + b;
a = b;
b = next;
co_yield next;
}
}
std::generator<int> outer() {
yield fib(); // (1)
yield std::ranges::elements_of(fib); // (2)
}
Der äußere Generator gibt in Zeile (1) den inneren std::generator<int> zurück, aber in Zeile (2) die Werte des inneren Generators. Beide Koroutinen besitzen den gleichen Rückgabetyp.
std::bind_back
Entsprechend zu std::bind_front in C++20 unterstützt C++23 std::bind_back. Das folgende Programm bindFrontBack.cpp zeigt die Anwendung der beiden Funktionen.
// bindFrontBack.cpp
#include <functional>
#include <iostream>
#include <string>
int main() {
std::cout << 'n';
auto add = [](Std :: String a, std :: String B, std :: String C) {dönüş a + b + c; }; Araba iki_three = std :: bind_front (ekle, "bir"); Std :: cout code>
Çıktı sayesinde program açıklanmalıdır.

Kısmi işlev uygulamaları hakkında daha fazla bilgi std::bind, std::bind_front VE std::bind_back "Yazılım Geliştirme Teknikleri: Kısmi Fonksiyon Uygulaması" makalemde mümkündür.
Sırada ne var?
Şimdi C ++ 23 ile bitirdim. Bu yüzden altı yıl geri dönmek istiyorum. Bir sonraki makalemde C ++ 17: Allocaters Polimorfik'te neredeyse bilinmeyen bir işlev hakkında yazacağım.
(RME)