Red Hat řeší bezpečnostní incident, při kterém došlo k neoprávněnému přístupu do GitLab instance používané jejich konzultačním týmem.
Immich byl vydán v první stabilní verzi 2.0.0 (YouTube). Jedná se o alternativu k výchozím aplikacím od Googlu a Applu pro správu fotografií a videí umožňující vlastní hosting serveru Immich. K vyzkoušení je demo. Immich je součástí balíčků open source aplikací FUTO. Zdrojové kódy jsou k dispozici na GitHubu pod licencí AGPL-3.0.
Český telekomunikační úřad vydal zprávy o vývoji cen a trhu elektronických komunikací se zaměřením na rok 2024. Jaká jsou hlavní zjištění? V roce 2024 bylo v ČR v rámci služeb přístupu k internetu v pevném místě přeneseno v průměru téměř 366 GB dat na jednu aktivní přípojku měsíčně – celkově jich tak uživateli bylo přeneseno přes 18 EB (Exabyte). Nejvyužívanějším způsobem přístupu k internetu v pevném místě zůstal v roce 2024 bezdrátový
… více »Raspberry Pi OS, oficiální operační systém pro Raspberry Pi, byl vydán v nové verzi 2025-10-01. Přehled novinek v příspěvku na blogu Raspberry Pi a poznámkách k vydání. Jedná o první verzi postavenou na Debianu 13 Trixie.
Byla vydána nová verze 4.6 svobodného notačního programu MuseScore Studio (Wikipedie). Představení novinek v oznámení v diskusním fóru a také na YouTube.
Společnost DuckDuckGo stojící za stejnojmenným vyhledávačem věnovala 1,1 milionu dolarů (stejně jako loni) na podporu digitálních práv, online soukromí a lepšího internetového ekosystému. Rozdělila je mezi 29 organizací a projektů. Za 15 let rozdala 8 050 000 dolarů.
Svobodný multiplatformní herní engine Bevy napsaný v Rustu byl vydán ve verzi 0.17. Díky 278 přispěvatelům.
Bylo vydáno openSUSE Leap 16 (cs). Ve výchozím nastavení přichází s vypnutou 32bitovou (ia32) podporou. Uživatelům však poskytuje možnost ji ručně povolit a užívat si tak hraní her ve Steamu, který stále závisí na 32bitových knihovnách. Změnily se požadavky na hardware. Leap 16 nyní vyžaduje jako minimální úroveň architektury procesoru x86-64-v2, což obecně znamená procesory zakoupené v roce 2008 nebo později. Uživatelé se starším hardwarem mohou migrovat na Slowroll nebo Tumbleweed.
Ministerstvo průmyslu a obchodu (MPO) ve spolupráci s Národní rozvojovou investiční (NRI) připravuje nový investiční nástroj zaměřený na podporu špičkových technologií – DeepTech fond. Jeho cílem je posílit inovační ekosystém české ekonomiky, rozvíjet projekty s vysokou přidanou hodnotou, podpořit vznik nových technologických lídrů a postupně zařadit Českou republiku mezi země s nejvyspělejší technologickou základnou.
… více »Radicle byl vydán ve verzi 1.5.0 s kódovým jménem Hibiscus. Jedná se o distribuovanou alternativu k softwarům pro spolupráci jako např. GitLab.
namespace { template<typename CharType = wchar_t> std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& inputStream, std::basic_string<CharType>& line) { std::getline(inputStream, line); return inputStream; } } template<typename CharType = char> auto ReadLines(std::wstring path) { auto inputStream = new std::ifstream(path); using iterator = std::istream_iterator<std::basic_string<CharType>>; auto begin = std::shared_ptr<iterator>( new iterator(*inputStream), [inputStream](auto* iterator) { delete iterator; delete inputStream; } ); return begin; }Je toto správne riešenie? Alebo na to idem zle? Lebo fungovať mi to funguje. Ak viete o niečom priamočiarejšom tak sem s tým. Ďakujem.
auto begin = ReadLines(L"c:\test\newFile21.txt"); for (auto it = *begin; it != std::istream_iterator<std::string>(); ++it) { std::cout << ":" << *it << "n"; }
#include <fstream> #include <iostream> #include <stdexcept> template <typename T> void read_lines(const std::string &path, T &&handler) { std::ifstream s{}; s.open(path); if (!s.is_open()) throw std::runtime_error{"Cannot open file"}; std::string str{}; while (std::getline(s, str).good()) handler(str); } int main() { try { read_lines("abc.txt", [](const std::string &s) { std::cout << s << std::endl; }); } catch (const std::runtime_error &ex) { std::cout << ex.what() << std::endl; } return 0; }
Začal bych od jednoduchého příkladu — implicitní iterace po slovech. To se zařídí třeba takhle:
#include <fstream> #include <iostream> #include <iterator> #include <string> namespace { template<typename C> struct ifstream_iterable { ifstream_iterable(const std::string &path) : stream_{path} {} auto begin() { return iterator{stream_}; } auto end() { return iterator{}; } private: typedef std::istream_iterator<std::basic_string<C>, C> iterator; std::basic_ifstream<C> stream_; }; } // namespace int main() { for (auto &w : ifstream_iterable<wchar_t>{"/proc/cpuinfo"}) std::wcout << w << std::endl; }
To bychom měli. Teď je otázka, jak z toho^^^ udělat iteraci po řádcích. Předně pár poznámek k tématu:
>>
je mírně špatně v mezích zákona, protože deklarace je hodně podobná této deklaraci v headeru <string>
, což sice na první pohled nevadí, ale na druhý pohled tam hraje roli až příliš mnoho složitých detailů kolem pravidel pro hledání identifikátorů. Drobná změna standardu a/nebo (kni)hovny může vést k tomu, že operátor se buď vůbec nepoužije, nebo začne být v konfliktu s operátory z (kni)hovny. Drobnou modifikací se mi podařilo vyrobit (proti)příklad, kdy clang++
i g++
kód přeloží bez varování, ale g++
„přetížený“ operátor použije, zatímco clang++
nikoliv.std::string
(což je sice technicky možné, ale z hlediska kompatibility a udržovatelnosti kódu je vhodné se takových nápadů vyvarovat)Co tedy podniknout? Třeba tohle:
#include <fstream> #include <iostream> #include <iterator> #include <string> #include <utility> namespace { template <typename C> struct line { std::basic_istream<C>& operator <<(std::basic_istream<C> &stream) { std::getline(stream, str_); return stream; } operator const std::basic_string<C>&() const & { return str_; } operator std::basic_string<C>&() & { return str_; } // zde se nepoužije operator std::basic_string<C>() && { return std::move(str_); } // -dtto- private: std::basic_string<C> str_; }; template <typename C> std::basic_istream<C>& operator >>(std::basic_istream<C> &stream, line<C> &str) { str << stream; return stream; } template<typename C> struct ifstream_iterable { ifstream_iterable(const std::string &path) : stream_{path} {} auto begin() { return iterator{stream_}; } auto end() { return iterator{}; } private: typedef std::istream_iterator<line<C>, C> iterator; std::basic_ifstream<C> stream_; }; } // namespace int main() { for (const std::wstring &l : ifstream_iterable<wchar_t>{"/proc/cpuinfo"}) std::wcout << l << std::endl; }
Tohle^^^ nedědí od základních typů, nevyvolává příliš mnoho nespecifikovaných rohových případů, nepoužívá kámoše a vystačí si s jednou třídou (dělnickou), kterou lze konvertovat na odpovídající string
. (Pro složitější konverze do jiného API si lze napsat deduction guides, ale to už je jiné téma. V této podobě se kód přeloží s C++ 14, 17 i 20, zatímco s deduction guides by vyžadoval minimálně C++17.)
Ještě závěrem dodám (a předejdu tak, doufám, některým komentářům), že někteří lidé mají utkvělou špatnou představu o sousloví return std::move(...);
— myslí si, že něco takového nedává smysl a že by to nemělo existovat. Samozřejmě se mýlí, jak jinak; tady jsou k tomu předdrobnosti i podrobnosti.
A když nad tím znova přemýšlím (což rozhodně nedělám často), čitelnější to bude bez toho nestandardního operátoru <<
, který nijak neinteraguje s (kni)hovnou a jenom všeho všudy mate čtenáře (včetně mě). Takže raději třeba takto:
#include <fstream> #include <iostream> #include <iterator> #include <string> #include <utility> namespace { template <typename C> struct line { operator const std::basic_string<C>&() const & { return str_; } operator std::basic_string<C>&() & { return str_; } operator std::basic_string<C>() && { return std::move(str_); } // nepoužito private: std::basic_string<C> str_; }; template <typename C> std::basic_istream<C>& operator >>(std::basic_istream<C> &stream, line<C> &str) { std::getline(stream, static_cast<std::basic_string<C>&>(str)); return stream; } template<typename C> struct ifstream_iterable { ifstream_iterable(const std::string &path) : stream_{path} {} auto begin() { return iterator{stream_}; } auto end() { return iterator{}; } private: typedef std::istream_iterator<line<C>, C> iterator; std::basic_ifstream<C> stream_; }; } // namespace int main() { for (const std::wstring &l : ifstream_iterable<wchar_t>{"/proc/cpuinfo"}) std::wcout << l << std::endl; }
Ale ak pri smartpointeroch používate deleter tak sa použitiu delete nevyhnete.
To je sice pravda, ale právě nadužívání dynamické alokace je u C++ poměrně častá chyba. Zrovna třeba statement delete iterator;
není dobrý nápad (a kdekoho přiměje zvednout obočí), protože iterátor má být (a většinou je) malý kousek dat (něco jako 16 B, dejme tomu), který se dá a má předávat všude hodnotou. (Samozřejmě kromě případu, kdy je potřeba z více míst měnit jeden iterátor, tj. mít něco jako dvouhvězdičkový pointer.)
Ještě bych poznamenal, jen tak pro úplnost, že příklad v dotazu by byl lepší s použitím std::unique_ptr
místo std::shared_ptr
. Zatímco std::unique_ptr
je jednoduchý zapouzdřený pointer, který vyjadřuje exkluzivní vlastnictví a vlastní z jednoho kontextu jeden kousek dat, std::shared_ptr
je složitá mašinerie s atomickým reference-countingem. Uvnitř v implementaci std::shared_ptr
neukazuje přímo na data, která spravuje, nýbrž na svou vlastní dynamickou strukturu, ve které má (kromě pointeru) také atomické počítadlo referencí a pár dalších vychytávek. (Dlužno navíc dodat, v souvislosti s atomickým počítadlem, že jedna atomická instrukce může stát čas srovnatelný s řádově tisícem sčítání.) Dá se říct, že std::shared_ptr
je v jistém smyslu thread-safe, byť s omezeními:
std::shared_ptr
, každou z jiného vlákna, lze používat paralelně zcela bez omezení.std::shared_ptr
několika vlákny (například rozumně atomické přiřazení toho sdíleného pointeru) ovšem samo od sebe atomické není; k tomu slouží specializace std::atomic<std::shared_ptr<...>>
.Zkrátka a dobře (nebo zdlouha a špatně, teď nevím),
std::unique_ptr
místo std::shared_ptr
, je to jasná volba, zejména z hlediska efektivity a jednoznačnosti vlastnictví objektů. Atomický reference-counting je potřebný jenom velmi zřídka, nikoliv zhusta.
Tiskni
Sdílej: