C++20x std::sregex_iterator - skrátený zápis for loop-u

ahojte C++ má syntaktický cukor ("foreach cyklus") pre prechádzanie objektov, ktoré obsahujú iterátor.

Kód: [Vybrat]
for (auto x : iterableObject)
{
}

každopádne ako doň prepísať toto:

Kód: [Vybrat]
auto linksBegin = std::sregex_iterator{ html.begin(), html.end(), linksRegex };
auto linksEnd = std::sregex_iterator{};

for (auto it = linksBegin; it != linksEnd; ++it) // dá sa tento riadok skrátiť?
{
auto match = *it;
if (match.size() > 2)
{
std::cout << match[2] << std::endl;
}
}


alex6bbc

  • *****
  • 1 432
    • Zobrazit profil
    • E-mail
Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #1 kdy: 11. 06. 2022, 08:29:25 »
ted me napada akorat si udelat vlastni tridu kde naimplementujes iterator a do te tridy das ten svuj regex.

tvoje trida bude podobna tride Range z prikladu https://en.cppreference.com/w/cpp/iterator/iterator
akorat nebude pro typ long, ale pro regex.

takze pak budes moci pouzit kratky zapis for s iteratorem z tvoji tridy, ale zase tam bude vice kodu kvuli vlastni tride.

Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #2 kdy: 11. 06. 2022, 09:22:49 »
Kód: [Vybrat]
std::for_each s lambdou, ale nevim, k čemu si tim pomůžeš

Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #3 kdy: 11. 06. 2022, 10:07:38 »
Nechcem nikoho poučovať, ale táto forma štúdia sa mi javí ako krajne nešťastná, a neefektívna, lebo vlepený kód odpovede pravdepodobne povedie iba k ďalšíemu miešaniu konceptov, prípadne vynechaniu základu, ktorý súvisiace koncepty spojuje.

Na začiatku by možno stálo za to zamyslieť sa nad tým, ako sa ten syntaktický cukor volá oficiálne.

V origináli je to range-based for loop, teda cyklus for založený na rozsahoch.

Loop, for, based sú asi jasné pojmy, takže kľúčové slovo pre ďalšie hľadanie a štúdium musí byť range.

Takže tie "objekty, ktoré obsahujú iterátor" majú pevne definovaný názov a v skutočnosti neobsahujú iterátor jeden, ale dva.

Jeden z nich je začiatok nejakého rozsahu, druhý jeho koniec (alebo niečo, čo sa dá za koniec považovať).

Najskôr sa rozsahy objavili asi v rámci knižníc boost, potom to značne rozvinul Eric Niebler v samostatnej knižnici, a nakoniec je to súčasťou C++20 ako jedna z niekoľkých veľkých vecí, ktoré boli do jazyka pridané.

Celkovo teda možnosti sú dve, buď to riešiť priamo iterátormi, čo je klasické riešenie, alebo použiť range, ktorý ich bude obsahovať, čo je moderné riešenie.

Okrem toho, C++, vzhľadom na jeho rozsiahlosť, históriu siahajúcu 40 rokov do minulosti a kvantá kódu, ktorý sa musí dať stále preložiť, nie je iba jazyk ako taký, ale aj sada odporúčaní, ktoré časti jazyka používať na písanie nového kódu, aby to bolo v súlade s tým, čo členovia normalizačného výboru zamýšľali.

A už minimálne 20 rokov je jedným z nich odporúčanie nepoužívať holé cykly, ale štandardné algoritmy. Síce neviem, či je to niekde napísané, ale dovolím si povedať, že sa to týka aj cyklu for založeného na rozsahoch.

Pretože čitateľovi stačí čítať názvy algoritmov a ich náväznosti a vie, čo sa v kóde deje, pričom čítanie tela cyklov vyžaduje hlbšie sústredenie na pochopenie.

Takže, riešenie založené na iterátoroch použije štandardný algoritmus na filtrovanie, ktorý berie iterátor začiatku rozsahu (v kontajneri alebo kdekoľvek) odkiaľ sa má kopírovať, iterátor konca a jednoduchú funkciu alebo (od C++11) lambdu vyhodnocujúcu jednotlivý element.

Výsledok by bol v štandardnom kontajneri a bol by spracovaný opäť štandardným algoritmom, v tomto prípade algoritmom kopírovania, ktorý opäť berie iterátor začiatku (zdroja), iterátor konca (zdroja) a iterátor na miesto kam sa majú jednotlivé elementy skopírovať

Tento musí byť vo forme výstupného iterátora, teda vlastne "ukazovateľa" na miesto, kam sa zapíše prvý kopírovaný element.

Najjednoduchšie sa kopíruje do kontajnerov, keďže ich iterátory zvyčajne vyhovujú požiadavkám kladeným na výstupné iterátory.

Navyše, algoritmus kopírovania predpokladá, že od miesta, kam sa zapíše prvý kopírovaný element existuje toľko elementov, koľko sa kopíruje.

Pokiaľ táto podmienka nie je splnená, je možné zabezpečiť, aby sa elementy do kontajnera vkladali za letu, teda počas kopírovania jednotlivých zdrojových elementov, a to sa robí tak, že do algoritmu kopírovania sa ako miesto pre prvú kopírovanú položku zadá cieľový kontajner obalený adaptérom, vo forme vkladacieho iterátora.

Lenže v zadaní je výstup do štandardného výstupného prúdu, teda nie do kontajnera, takže sa nepoužije vkladací iterátor, ale iterátor výstupného prúdu, ktorý zabezpečí kompatibilitu s požiadavkami algoritmu, teda je vo forme výstupného iterátora.

No, a konečne sa dostávame k rozsahom. Tie tiež majú svoje štandardné algoritmy, len ako vstup neberú jednotlivé iterátory, ale kompletný rozsah, ktorý obsahuje iterátor svojho začiatku aj iterátor svojho konca.

A aby sa to písalo ešte jednoduchšie, tak už od rozsahov knižnice boost sa dajú písať konštrukcie, kedy jednotlivé algoritmy je možné zreťaziť použitím operátora |, čím vzniká veľmi elegantný zápis nie nepodobný kolone príkazov ako ich má UNIX, alebo aj PowerShell. A určite to preniká aj do iných jazykov.

Ale s týmto sme sa už v tomto fóre stretli, a to konkrétne tu: https://forum.root.cz/index.php?topic=23399.0

Čo iba potvrdzuje môj dojem z prvého odstavca tohto príspevku.

No a na záver: už v rozsahoch knižnice boost bolo možné triviálne vytvoriť rozsah z dvoch iterátorov a osobne nevidím dôvod, aby táto možnosť nebola aj v štandardnej knižnici C++20.

anonacct

Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #4 kdy: 11. 06. 2022, 19:42:08 »
Regex je deprecated, byl to omyl to tam vůbec dávat.


alex6bbc

  • *****
  • 1 432
    • Zobrazit profil
    • E-mail
Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #5 kdy: 11. 06. 2022, 20:23:34 »
Regex je deprecated, byl to omyl to tam vůbec dávat.

proc je deprecated?

anonacct

Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #6 kdy: 11. 06. 2022, 21:03:02 »
Protože ten design je tak debilní, že už s tím nic neudělají.

https://www.reddit.com/r/cpp/comments/f47x4o/202002_prague_iso_c_committee_trip_report_c20_is/

Citace
We declined to forward a paper to enhance std::regex to better support Unicode due to severe ABI restrictions; the std::regex design exposes many internal details of the implementation to the ABI and implementers indicated that they cannot make any significant changes. Given the current state of std::regex is such that we cannot fix either its interface or its well-known performance issues, a number of volunteers agreed to bring a paper to deprecate std::regex at a future meeting.

Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #7 kdy: 12. 06. 2022, 00:08:00 »
Problém neni v designu, existuje implementace plně podporující unicode (SRELL) se stejným interface, jako má regex. Problém je v posedlosti C++ neměnit ABI, což znamená, že nejde měnit binární interface standardní knihovny. Prakticky se stabilní ABI ale stejně nedá udržet, např. změna std::string v C++11 si vynutila rozbití ABI, takže tahle snaha o neměnné ABI je dost diskutabilní.

nula

Re:C++20x std::sregex_iterator - skrátený zápis for loop-u
« Odpověď #8 kdy: 13. 06. 2022, 06:54:20 »
No, popravde zasadni pravidlo je nepouzivat std::regex.
Je to strasne spatne udelany kus kodu, ktery kvuli binarni kompatibilite ani nejde opravit.
Pouzil bych naky 3rd party knihovnu pro regexy. Treba pcre.
IMO by se sice v STL velmi hodila naka slusna verze regexu, ale to co tam je ted je fakt k nicemu.

Jinak, popravde ani se mi nechce zkouset jestli to bude fungovat, protoze fakt std::regex je zlo, ale
asi by si stacilo nadefinovat begin() a end() pro  std::sregex_iterator a ten pak pouzit v tom range foru. Pripadne jakoukoli obalovou tridu, ktera ma metody begin() a end()