{"id":32466,"date":"2019-10-31T21:47:13","date_gmt":"2019-10-31T18:47:13","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17\/"},"modified":"2019-10-31T21:47:13","modified_gmt":"2019-10-31T18:47:13","slug":"kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","title":{"rendered":"Kako smo preveli 10 milijuna redaka C++ koda na standard C++14 (a potom i na C++17)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Nekoliko vremena unazad (jesen 2016), prilikom razvoja nove verzije tehnolo\u0161ke platforme 1C:Poduze\u0107e, unutar tima za razvoj postavilo se pitanje podr\u0161ke novom standardu <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/C%2B%2B14\">C++14<\/a><\/noindex> u na\u0161em kodu. Prelazak na novi standard, kao \u0161to smo pretpostavljali, omogu\u0107io bi nam da pi\u0161emo mnoge stvari elegantnije, jednostavnije i pouzdanije, olak\u0161avaju\u0107i podr\u0161ku i odr\u017eavanje koda. A u prevodu, kao da ne postoji ni\u0161ta neobi\u010dno, da nije razmere kodne baze i specifi\u010dnih karakteristika na\u0161eg koda.<\/p>\n<p>Za one koji ne znaju, 1C:Poduze\u0107e \u2013 to je okru\u017eenje za brzi razvoj multiplatformskih poslovnih aplikacija i runtime za njihovo izvr\u0161avanje na razli\u010ditim operativnim sistemima i DBMS. U op\u0161tem smislu, proizvoda uklju\u010duje:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000885.htm\">Klaster aplikacijskih servera<\/a><\/noindex>, radi na Windows i Linuxu<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000124.htm\">Klijent<\/a><\/noindex>, koji komunicira sa serverom putem http(s) ili sopstvenog binarnog protokola, radi na Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/315414\/\">Web-klijent<\/a><\/noindex>, koji funkcioni\u0161e u browserima Chrome, Internet Explorer, Microsoft Edge, Firefox, Safari (napisan na JavaScript)<\/li>\n<li>Razvojno okru\u017eenje (<noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000008.htm\">Konfigurator<\/a><\/noindex>), radi na Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000813.htm\">Alati za administraciju<\/a><\/noindex> aplikacijskih servera, rade na Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/wonderland.v8.1c.ru\/blog\/mobilnyy-klient\/\">Mobilni klijent<\/a><\/noindex>, povezuje se sa serverom putem http(s), radi na mobilnim ure\u0111ajima koji koriste Android, iOS, Windows<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/283198\/\">Mobilna platforma<\/a><\/noindex> \u2014 okvir za izgradnju offline mobilnih aplikacija s mogu\u0107no\u0161\u0107u sinhronizacije, radi na Android, iOS, Windows<\/li>\n<li>Razvojno okru\u017eenje <noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/IDE\/\">1C:Enterprise Development Tools<\/a><\/noindex>, napisan na Javi<\/li>\n<li>Server <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/422903\/\">Sistemi interakcije<\/a><\/noindex><\/li>\n<\/ul>\n<p>\nTrudimo se maksimalno da napi\u0161emo jedan kod za razli\u010dite OS \u2013 kodna baza servera je zajedni\u010dka u 99%, klijent \u2013 otprilike 95%. Tehnolo\u0161ka platforma 1C:Poduze\u0107e ve\u0107inom je napisana na C++ i u nastavku su pribl\u017ene karakteristike koda:<\/p>\n<ul>\n<li>10 miliona redova C++ koda,<\/li>\n<li>14 hiljada datoteka,<\/li>\n<li>60 hiljada klasa,<\/li>\n<li>pol miliona metoda.<\/li>\n<\/ul>\n<p>\nI sve to imanje trebalo je prevesti na C++14. O tome kako smo to radili i s \u010dim smo se suo\u010dili tokom procesa, danas \u0107emo govoriti.<\/p>\n<p><img decoding=\"async\" alt=\"Kako smo preveli 10 milijuna redaka C++ koda na standard C++14 (a potom i na C++17)\" src=\"\/wp-content\/uploads\/2019\/04\/7f9270bc37fa9fd462ac9efbb12f0764.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Odricanje<\/h3>\n<p>\nSve \u0161to je napisano u nastavku o sporom\/brzom radu i (ne)velikom potro\u0161njom memorije standardnih klasa u razli\u010ditim bibliotekama zna\u010di jedno: to se odnosi na NAS. Mogu\u0107e je da \u0107e standardne implementacije najbolje odgovarati va\u0161im potrebama. Mi smo se vodili na\u0161im zadacima: uzimali uobi\u010dajene podatke na\u0161ih klijenata, provodili tipi\u010dne scenarije, pratili performanse, potro\u0161nju memorije itd., i analizirali \u2013 jesu li nas i na\u0161e klijente takvi rezultati zadovoljavali ili ne. I postupali smo u skladu s tim.<\/p>\n<h3>\u0160to smo imali<\/h3>\n<p>\nIsprva smo pisali kod platforme 1C:Poduze\u0107e 8 u Microsoft Visual Studio. Projekt je zapo\u010deo po\u010detkom 2000-ih i imali smo verziju samo za Windows. Naravno, od tada se kod aktivno razvijao, mnogi mehanizmi su potpuno prepisani. No kod je pisan prema standardu iz 1998. godine, i, na primjer, desne uglaste zagrade bile su odvojene razmacima kako bi se kompilacija uspje\u0161no zavr\u0161ila, ovako:<\/p>\n<pre><code class=\"cpp\">vector&lt;vector &gt; IntV;<\/code><\/pre>\n<p>\nGodine 2006., s izlaskom verzije platforme 8.1, po\u010deli smo podr\u017eavati Linux i pre\u0161li na vanjsku standardnu biblioteku <noindex><a rel=\"nofollow\" href=\"http:\/\/www.stlport.org\/\">STLPort<\/a><\/noindex>. Jedan od razloga prelaska bila je podr\u0161ka za \u0161iroke nizove. U na\u0161em kodu svuda koristimo std::wstring, koji se temelji na tipu wchar_t. Njegova veli\u010dina u Windowsu je 2 bajta, a u Linuxu po defaultu 4 bajta. To je dovodilo do nespojivosti na\u0161ih binarnih protokola izme\u0111u klijenta i poslu\u017eitelja, kao i razli\u010ditih perzistentnih podataka. Opcijama gcc mo\u017ee se navesti da veli\u010dina wchar_t pri kompilaciji bude tako\u0111er 2 bajta, ali tada se mo\u017ee zaboraviti na kori\u0161tenje standardne biblioteke od kompajlera, budu\u0107i da koristi glibc, koja je, pak, skompajlirana za 4-bajtni wchar_t. Drugi razlozi uklju\u010divali su kvalitetniju implementaciju standardnih klasa, podr\u0161ku za hash tablice i \u010dak emulaciju semantike premje\u0161tanja unutar kontejnera, koju smo aktivno koristili. A jo\u0161 jedan razlog, kao \u0161to ka\u017eu, posljednji ali ne manje va\u017ean, bila je performansa nizova. Imali smo svoju klasu za nizove, jer se u na\u0161em softveru, zbog specifi\u010dnosti, operacije s nizovima koriste vrlo \u0161iroko i to je za nas klju\u010dno. <\/p>\n<p>Na\u0161 niz temelji se na idejama optimizacije nizova koje je iznio jo\u0161 po\u010detkom 2000-ih <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B5%D1%81%D0%BA%D1%83,_%D0%90%D0%BD%D0%B4%D1%80%D0%B5%D0%B9\">Andrei Alexandrescu<\/a><\/noindex>. Kasnije, dok je Alexandrescu radio u Facebooku, na njegovu inicijativu u tra\u017eilici Facebook upotrebljena je funkcija koja radi na sli\u010dnim principima (vidi knji\u017enicu <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/folly\">folly<\/a><\/noindex>).<\/p>\n<p>. U na\u0161em stringu kori\u0161tene su dvije glavne tehnologije optimizacije:<\/p>\n<ol>\n<li>Za kratke vrijednosti koristi se unutarnji buferski pohrana u samom objektu stringa (ne zahtijevaju\u0107i dodatnu alokaciju memorije).<\/li>\n<li>Za sve ostale koristi se mehanika <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8\">Copy On Write<\/a><\/noindex>. Vrijednost stringa pohranjuje se na jednom mjestu, a prilikom dodjele\/modifikacije koristi se broja\u010d referenci.<\/li>\n<\/ol>\n<p>\nKako bismo ubrzali kompilaciju platforme, isklju\u010dili smo iz na\u0161e verzije STLPort implementaciju streama (koju nismo koristili), \u0161to nam je dalo ubrzanje kompilacije otprilike 20%. Kasnije smo ograni\u010deno morali koristiti <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Boost\">Boost<\/a><\/noindex>. Boost aktivno koristi stream, posebno u svojim servisnim API-jima (na primjer, za logiranje), pa smo morali modificirati na\u0161u verziju isklju\u010duju\u0107i kori\u0161tenje streama. To nam je, pak, ote\u017ealo prijelaz na nove verzije Boost. <\/p>\n<h3>Tre\u0107i put<\/h3>\n<p>\nPrilikom prijelaza na standard C++14 razmatrali smo takve opcije:<\/p>\n<ol>\n<li>Podizanje modificiranog STLPort-a na standard C++14. Opcija je vrlo slo\u017eena, budu\u0107i da je podr\u0161ka za STLPort prekinuta 2010. godine, a sav njegov kod morali bismo podi\u0107i sami.<\/li>\n<li>Prijelaz na drugu implementaciju STL-a, kompatibilnu s C++14. Izuzetno je po\u017eeljno da ova implementacija bude pod Windows i Linux.<\/li>\n<li>Kori\u0161tenje prikladne biblioteke ugra\u0111ene u odgovaraju\u0107i kompajler prilikom kompilacije za svaku OS.<\/li>\n<\/ol>\n<p>\nPrva opcija odmah je odbijena zbog prevelikog obujma rada.<\/p>\n<p>Nekoliko smo vremena razmi\u0161ljali o drugoj opciji; kao kandidata razmatrali smo <noindex><a rel=\"nofollow\" href=\"https:\/\/libcxx.llvm.org\/\">libc++<\/a><\/noindex>, ali u to vrijeme nije radio pod Windows. Da bismo portirali libc++ na Windows, trebalo bi obaviti mnogo posla \u2014 na primjer, sami napisati sve \u0161to se ti\u010de niti, sinkronizacije niti i atomskih operacija, budu\u0107i da je libc++ u tim podru\u010djima koristio <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/POSIX\">POSIX API<\/a><\/noindex>.<\/p>\n<p>I izabrali smo tre\u0107i put.<\/p>\n<h3>Prijelaz<\/h3>\n<p>\nDakle, morali smo zamijeniti kori\u0161tenje STLPort-a s knji\u017enicama odgovaraju\u0107ih kompajlera (Visual Studio 2015 za Windows, gcc 7 za Linux, clang 8 za macOS). <\/p>\n<p>Na sre\u0107u, na\u0161 kod je uglavnom pisan prema smjernicama i nije koristio razne lukav\u0161tine, tako da je migracija na nove biblioteke prolazila relativno glatko, uz pomo\u0107 skripti koje su zamjenjivale imena tipova, klasa, prostora imena i uklju\u010divanja u izvorne datoteke. Migracija je obuhvatila 10 000 izvornika (od 14 000). wchar_t je zamijenjen sa char16_t; odlu\u010dili smo se odustati od kori\u0161tenja wchar_t, jer char16_t na svim OS-ima zauzima 2 bajta i ne kvari kompatibilnost koda izme\u0111u Windowsa i Linuxa.<\/p>\n<p>Nije pro\u0161lo bez malih avantura. Na primjer, u STLPort-u se iterator mogao implicitno castati u pokaziva\u010d na element, i na nekim mjestima na\u0161eg koda to je kori\u0161teno. U novim bibliotekama to vi\u0161e nije bilo mogu\u0107e, pa su ta mjesta morala biti analizirana i ru\u010dno prepisana. <\/p>\n<p>Dakle, migracija koda je zavr\u0161ena, kod se kompajlira za sve OS-e. Do\u0161lo je vrijeme za testiranje. <\/p>\n<p>Testovi nakon prelaska su pokazali pad performansi (na nekim mjestima do 20-30%) i pove\u0107anje potro\u0161nje memorije (do 10-15%) u usporedbi sa starom verzijom koda. To je bilo, izme\u0111u ostalog, povezano s neoptimalnim radom standardnih stringova. Zato smo opet morali koristiti na\u0161u, malo doradjenu verziju stringova. <\/p>\n<p>Tako\u0111er se pokazala zanimljiva karakteristika implementacije spremnika u ugra\u0111enim bibliotekama: prazni (bez elemenata) std::map i std::set iz ugra\u0111enih biblioteka alociraju memoriju. A kod nas, zbog osobitosti implementacije, u nekim dijelovima koda se stvara prili\u010dno mnogo praznih spremnika ovog tipa. Standardni spremnici alociraju malo memorije, za jedan korijenski element, ali za nas je to bilo kriti\u010dno \u2013 u nekoliko scenarija smo osjetno izgubili performanse i pove\u0107ali potro\u0161nju memorije (u usporedbi sa STLPort-om). Stoga smo u na\u0161em kodu zamijenili ta dva tipa spremnika iz ugra\u0111enih biblioteka njihovom implementacijom iz Boost-a, gdje ti spremnici nisu imali tu osobinu, i to je rije\u0161ilo problem usporavanja i pove\u0107ane potro\u0161nje memorije.<\/p>\n<p>Kao \u0161to to obi\u010dno biva nakon opse\u017enih promjena u velikim projektima, prva iteracija izvora nije radila bez problema, i ovdje nam je posebno pomogla podr\u0161ka od debug iteratora u Windows implementaciji. Korak po korak napredovali smo, i do prolje\u0107a 2017 (verzija 8.3.11 1C: Predmet) migracija je bila zavr\u0161ena. <\/p>\n<h3>Zaklju\u010dci<\/h3>\n<p>\nPrijelaz na standard C++14 trajao je oko 6 mjeseci. Ve\u0107i dio vremena na projektu radio je jedan (ali vrlo kvalificirani) programer, a u zavr\u0161noj fazi pridru\u017eili su se predstavnici timova odgovornih za specifi\u010dna podru\u010dja \u2014 UI, klaster servera, razvojna i administracijska sredstva itd.<\/p>\n<p>Prijelaz nam je mnogo olak\u0161ao rad na migraciji na najnovije verzije standarda. Tako je verzija 1C:Preduze\u0107e 8.3.14 (u razvoju, izdanje je planirano za po\u010detak sljede\u0107e godine) ve\u0107 prevedena na standard <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/C%2B%2B17\">C++17<\/a><\/noindex>. <\/p>\n<p>Nakon migracije programeri su dobili vi\u0161e mogu\u0107nosti. Ako smo ranije imali vlastitu prera\u0111enu verziju STL i jedan naziv prostor std, sada se u nazivnom prostoru std nalaze standardne klase iz ugra\u0111enih biblioteka kompajlera, u nazivnom prostoru stdx \u2013 na\u0161i, optimizirani za na\u0161e zadatke stringovi i kontejneri, u boost \u2013 svje\u017ea verzija boosta. Programer koristi one klase koje optimalno odgovaraju rje\u0161avanju njegovih zadataka. <\/p>\n<p>Poma\u017ee u razvoju tako\u0111er i 'izvorna' implementacija konstruktora premje\u0161tanja (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/move_constructor\">move constructors<\/a><\/noindex>) za niz klasa. Ako klasa ima konstruktor premje\u0161tanja i ta se klasa smjesti u kontejner, STL optimizira kopiranje elemenata unutar kontejnera (na primjer, kada se kontejner pro\u0161iruje i treba promijeniti kapacitet i reallocirati memoriju). <\/p>\n<h3>Ka\u0161ika katrana<\/h3>\n<p>\nNajneugodnija (ali ne kriti\u010dna) posljedica migracije \u2014 susreli smo se s pove\u0107anjem volumena <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D1%8B%D0%B9_%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C\">obj-datoteka<\/a><\/noindex>, a kona\u010dni rezultat gradnje sa svim me\u0111ufajlovima postao je 60 \u2013 70 GB. Takvo pona\u0161anje povezano je s karakteristikama modernih standardnih biblioteka, koje su postale manje kriti\u010dne prema volumenu generiranih pomo\u0107nih datoteka. To ne utje\u010de na rad kompajlirane aplikacije, ali donosi odre\u0111ene neugodnosti u razvoju, osobito pove\u0107ava vrijeme kompajlacije. Tako\u0111er se pove\u0107avaju zahtjevi za slobodnim prostorom na disku na build serverima i na ra\u010dunalima programera. Na\u0161i programeri paralelno rade na nekoliko verzija platforme, a stotine gigabajta me\u0111ufajlova ponekad stvaraju pote\u0161ko\u0107e u radu. Problem je neugodan, ali nije kriti\u010dan, njegovo rje\u0161enje smo zasad odgodili. Kao jedan od mogu\u0107ih na\u010dina re\u0161enja razmatramo tehniku <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Single_Compilation_Unit\">unity build<\/a><\/noindex> (to je, izme\u0111u ostalog, koristi Google prilikom razvijanja preglednika Chrome).<br \/>\n<br \/>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/1c\/blog\/429678\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 C++14 \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u043b\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0431\u044b \u043d\u0430\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u0432\u0435\u0449\u0438 \u044d\u043b\u0435\u0433\u0430\u043d\u0442\u043d\u0435\u0439, \u043f\u0440\u043e\u0449\u0435 \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u0435\u0439, \u0443\u043f\u0440\u043e\u0449\u0430\u043b \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430. \u0418 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u0432\u0440\u043e\u0434\u0435 \u0431\u044b \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u044d\u043a\u0441\u0442\u0440\u0430\u043e\u0440\u0434\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24270,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32466","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u043b\u0438 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 C++ \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++14 (\u0430 \u043f\u043e\u0442\u043e\u043c \u0438 \u043d\u0430 C++17) | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:47:13+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:47:13+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47 Kako smo preveli 10 milijuna linija C++ koda na standard C++14 (a zatim i na C++17) | ProHoster","description":"Nekoliko vremena unazad (jesen 2016), prilikom razvoja nove verzije tehnolo\u0161ke platforme 1C:Poduze\u0107e, unutar tima za razvoj postavilo se pitanje podr\u0161ke novom standardu","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u043b\u0438 10 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 C++ \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 C++14 (\u0430 \u043f\u043e\u0442\u043e\u043c \u0438 \u043d\u0430 C++17) | ProHoster","og:description":"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 (\u043e\u0441\u0435\u043d\u044c\u044e 2016), \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b 1\u0421:\u041f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0430\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:47:13+00:00","article:modified_time":"2019-10-31T18:47:13+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32466","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 11:00:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:58:23","updated":"2026-01-21 11:00:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/32466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=32466"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/32466\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/24270"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=32466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=32466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=32466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}