{"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\/da\/blog\/administrirovanie\/kak-my-pereveli-10-millionov-strok-koda-c-na-standart-c-14-a-potom-i-na-c-17","title":{"rendered":"Hvordan vi oversatte 10 millioner linjer C++ kode til standard C++14 (og derefter til C++17)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>For some time (in the fall of 2016), during the development of the next version of the 1C:Enterprise technology platform, the question arose within the development team about supporting the new standard <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/C%2B%2B14\">C++14<\/a><\/noindex> in our code. Transitioning to the new standard, as we assumed, would allow us to write many things more elegantly, simply, and reliably, making code support and maintenance easier. And while there seems to be nothing extraordinary in the translation, the scale of the codebase and the specific features of our code make it different.<\/p>\n<p>For those who don't know, 1C:Enterprise is an environment for rapid development of cross-platform business applications and a runtime for executing them in various operating systems and DBMS. Broadly speaking, the product includes:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000885.htm\">A cluster of application servers<\/a><\/noindex>, operates on Windows and Linux<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000124.htm\">Kunde<\/a><\/noindex>, working with the server via http(s) or through its own binary protocol, runs on Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/315414\/\">A web client<\/a><\/noindex>, works in browsers like Chrome, Internet Explorer, Microsoft Edge, Firefox, Safari (written in JavaScript)<\/li>\n<li>Development environment (<noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000008.htm\">Configurator<\/a><\/noindex>), operates on Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/Term_000000813.htm\">Administration tools<\/a><\/noindex> for application servers, run on Windows, Linux, macOS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/wonderland.v8.1c.ru\/blog\/mobilnyy-klient\/\">A mobile client<\/a><\/noindex>, connecting to the server via http(s), operates on mobile devices running Android, iOS, Windows<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/283198\/\">A mobile platform<\/a><\/noindex> \u2014 a framework for creating offline mobile applications with synchronization capabilities, working on Android, iOS, Windows<\/li>\n<li>Development Environment <noindex><a rel=\"nofollow\" href=\"http:\/\/v8.1c.ru\/overview\/IDE\/\">1C:Enterprise Development Tools<\/a><\/noindex>, written in Java<\/li>\n<li>Server <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/1c\/blog\/422903\/\">Interaktionssystemer<\/a><\/noindex><\/li>\n<\/ul>\n<p>\nWe try as much as possible to write a single code for different operating systems \u2014 the server codebase is 99% shared, the client \u2014 about 95%. The 1C:Enterprise technology platform is predominantly written in C++, and below are approximate characteristics of the code:<\/p>\n<ul>\n<li>10 million lines of C++ code,<\/li>\n<li>14 thousand files,<\/li>\n<li>60 thousand classes,<\/li>\n<li>half a million methods.<\/li>\n<\/ul>\n<p>\nAnd all this needed to be transitioned to C++14. Today we will tell you how we did it and what challenges we faced in the process.<\/p>\n<p><img decoding=\"async\" alt=\"Hvordan vi oversatte 10 millioner linjer C++ kode til standard C++14 (og derefter til 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>Fraskrivelse<\/h3>\n<p>\nAlt, at der er n\u00e6vnt hurtig\/langsom ydelse, (ikke) stort hukommelsesforbrug i de standardklasser, der findes i forskellige biblioteker, betyder \u00e9n ting: dette g\u00e6lder FOR OS. Det er helt muligt, at standardimplementeringer fungerer bedst til dine opgaver. Vi har dog taget udgangspunkt i vores egne behov: vi arbejdede med typiske data fra vores kunder, k\u00f8rte dem gennem standard scenarier, s\u00e5 p\u00e5 hastigheden, hukommelsesforbruget osv., og analyserede \u2013 om disse resultater tilfredsstiller os og vores kunder eller ej. Og vi handlede derefter.<\/p>\n<h3>Hvad vi havde<\/h3>\n<p>\nOprindeligt skrev vi koden til platformen 1C:Enterprise 8 i Microsoft Visual Studio. Projektet startede i begyndelsen af 2000'erne, og vi havde kun en version til Windows. Naturligvis er koden siden da blevet kraftigt udviklet, mange mekanismer er blevet genkodet helt. Men koden blev skrevet efter standarden fra 1998, og for eksempel var de h\u00f8jre vinkelparenteser adskilt af mellemrum for at kunne kompileres, s\u00e5dan her:<\/p>\n<pre><code class=\"cpp\">vector&lt;vector &gt; IntV;<\/code><\/pre>\n<p>\nI 2006, med udgivelsen af version 8.1 af platformen, begyndte vi at st\u00f8tte Linux og skiftede til et tredjeparts standardbibliotek <noindex><a rel=\"nofollow\" href=\"http:\/\/www.stlport.org\/\">STLPort<\/a><\/noindex>. En af grundene til overgangen var arbejdet med brede strenge. I vores kode bruger vi udbredt std::wstring, baseret p\u00e5 typen wchar_t. Dens st\u00f8rrelse er 2 byte i Windows, mens den i Linux som standard er 4 byte. Dette f\u00f8rte til inkompatibilitet mellem vores bin\u00e6re protokoller mellem klient og server, samt forskellige persistente data. Med gcc's indstillinger kan man angive, at st\u00f8rrelsen p\u00e5 wchar_t ved kompilering ogs\u00e5 skal v\u00e6re 2 byte, men s\u00e5 kan man glemme at bruge standardbiblioteket fra compileren, da det bruger glibc, som er kompileret til 4-byte wchar_t. Andre grunde var en bedre implementering af standardklasser, support til hash-tabeller og endda emulering af flytningens semantik inden for containere, som vi brugte aktivt. Og en anden grund, som man siger, sidst men ikke mindst, var ydeevnen af strenge. Vi havde vores egen klasse til strenge, da string operationer i vores software er meget udbredte og kritiske for os. <\/p>\n<p>Vores streng er baseret p\u00e5 ideerne om optimering af strenge, fremsat allerede i begyndelsen af 2000'erne <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>. Senere, da Alexandrescu arbejdede hos Facebook, blev en lignende streng, der fungerede p\u00e5 tilsvarende principper, implementeret i Facebooks motor (se biblioteket <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/facebook\/folly\">folly<\/a><\/noindex>).<\/p>\n<p>I vores streng brugte vi to prim\u00e6re optimeringsteknologier:<\/p>\n<ol>\n<li>Til korte v\u00e6rdier bruges en intern buffer i selve strengobjektet (som ikke kr\u00e6ver yderligere hukommelsestildeling).<\/li>\n<li>For alle andre bruges mekanikken <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>. Strengens v\u00e6rdi opbevares \u00e9t sted, og ved tildeling\/modifikation benyttes en referenceopt\u00e6lling.<\/li>\n<\/ol>\n<p>\nFor at fremskynde platformens kompilation udelukkede vi stream-implementeringen fra vores version af STLPort (som vi ikke brugte), hvilket gav os en kompilationseffektivisering p\u00e5 cirka 20%. Senere m\u00e5tte vi begr\u00e6nset bruge <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/Boost\">Boost<\/a><\/noindex>. Boost bruger aktivt stream, s\u00e6rligt i sine service-API'er (f.eks. til logning), og derfor var vi n\u00f8dt til at modificere det og ekskludere brugen af stream. Dette gjorde igen overgangen til nye versioner af Boost vanskelig for os. <\/p>\n<h3>Den tredje vej<\/h3>\n<p>\nVed overgangen til standard C++14 overvejede vi s\u00e5danne muligheder:<\/p>\n<ol>\n<li>At opgradere den modificerede STLPort til standard C++14. Denne mulighed er meget udfordrende, da st\u00f8tten til STLPort blev stoppet i 2010, og vi ville skulle opgradere hele dens kode selv.<\/li>\n<li>Overgang til en anden STL-implementering, der er kompatibel med C++14. Det er st\u00e6rkt \u00f8nskeligt, at denne implementering fungerer p\u00e5 Windows og Linux.<\/li>\n<li>At bruge den indbyggede biblioteksfunktion fra den relevante compiler under kompilering for hver OS.<\/li>\n<\/ol>\n<p>\nDen f\u00f8rste mulighed blev straks afvist p\u00e5 grund af det for store arbejdsomfang.<\/p>\n<p>Vi overvejede l\u00e6nge den anden mulighed; som kandidat overvejede vi <noindex><a rel=\"nofollow\" href=\"https:\/\/libcxx.llvm.org\/\">libc++<\/a><\/noindex>, men den fungerede ikke p\u00e5 det tidspunkt p\u00e5 Windows. For at portere libc++ til Windows ville vi skulle udf\u00f8re en betydelig amount arbejde - for eksempel skrive alt, der relaterede til tr\u00e5de, tr\u00e5d-synkronisering og atomaritet selv, da libc++ brugte <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/POSIX\">POSIX API<\/a><\/noindex>.<\/p>\n<p>Og vi valgte den tredje vej.<\/p>\n<h3>Overgang<\/h3>\n<p>\nS\u00e5 vi skulle erstatte brugen af STLPort med bibliotekerne fra de relevante compilere (Visual Studio 2015 til Windows, gcc 7 til Linux, clang 8 til macOS). <\/p>\n<p>Heldigvis blev vores kode hovedsageligt skrevet i henhold til retningslinjerne og brugte ikke forskellige snedige tricks, s\u00e5 migreringen til de nye biblioteker forl\u00f8b relativt glat ved hj\u00e6lp af scripts, der erstattede type-, klasse-, navnerums- og include-navne i kildefilerne. Migreringen omfattede 10.000 kildefiler (ud af 14.000). wchar_t blev erstattet med char16_t; vi besluttede at opgive brugen af wchar_t, da char16_t p\u00e5 alle operativsystemer optager 2 byte og ikke \u00f8del\u00e6gger kodekompatibiliteten mellem Windows og Linux.<\/p>\n<p>Det blev ikke uden lidt eventyr. For eksempel kunne en iterator i STLPort implicit castes til en pointer til et element, og dette blev brugt nogle steder i vores kode. I de nye biblioteker var det ikke l\u00e6ngere muligt, og disse steder m\u00e5tte analyseres og skrives om manuelt. <\/p>\n<p>S\u00e5 migreringen af koden er afsluttet, og koden kompilere for alle operativsystemer. Det er tid til tests. <\/p>\n<p>Testene efter overgangen viste et fald i ydeevnen (nogle steder op til 20-30%) og en stigning i det forbrugte hukommelse (op til 10-15%) sammenlignet med den gamle version af koden. Dette h\u00e6ngte blandt andet sammen med den suboptimale funktionalitet af standardstrenge. Derfor m\u00e5tte vi igen bruge vores egen, lidt tilpassede streng. <\/p>\n<p>Der opstod ogs\u00e5 en interessant egenskab ved implementeringen af containere i indbyggede biblioteker: tomme (uden elementer) std::map og std::set fra de indbyggede biblioteker allokerer hukommelse. I vores kode, p\u00e5 grund af implementeringsspecifikationer, blev der oprettet en del tomme containere af denne type. De standardcontainere tildeler lidt hukommelse, for et rod element, men for os viste det sig at v\u00e6re kritisk \u2013 i en r\u00e6kke scenarier faldt vores ydeevne betydeligt, og hukommelsesforbruget steg (sammenlignet med STLPort). Derfor erstattede vi i vores kode disse to typer containere fra de indbyggede biblioteker med deres implementering fra Boost, hvor disse containere ikke havde denne egenskab, og det l\u00f8ste problemet med forsinkelse og \u00f8get hukommelsesforbrug.<\/p>\n<p>Som det ofte sker efter omfattende \u00e6ndringer i store projekter, fungerede den f\u00f8rste iteration af koden ikke uden problemer, og her var st\u00f8tte fra de debugger-iteratorer i Windows-implementeringen s\u00e6rligt nyttig. Skridt for skridt bev\u00e6gede vi os fremad, og i for\u00e5ret 2017 (version 8.3.11 1C:Enterprise) var migreringen afsluttet. <\/p>\n<h3>Resum\u00e9<\/h3>\n<p>\nOvergangen til standard C++14 tog os omkring 6 m\u00e5neder. St\u00f8rstedelen af tiden arbejdede en (meget kvalificeret) udvikler alene p\u00e5 projektet, men i den endelige fase blev repr\u00e6sentanter fra de teams, der var ansvarlige for specifikke omr\u00e5der \u2014 UI, klynger af servere, udviklings- og administrationsv\u00e6rkt\u00f8jer osv., involveret.<\/p>\n<p>Overgangen gjorde det betydeligt lettere for os at migrere til de nyeste versioner af standarden. S\u00e5ledes er version 1C:Enterprise 8.3.14 (under udvikling, release planlagt til starten af n\u00e6ste \u00e5r) allerede oversat til standarden. <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/C%2B%2B17\">C++17<\/a><\/noindex>. <\/p>\n<p>Efter migreringen har udviklerne f\u00e5et flere muligheder. Tidligere havde vi vores egen tilpassede version af STL og et namespace std, men nu indeholder namespace std standardklasser fra compilerens indbyggede biblioteker, i namespace stdx \u2014 vores, optimerede strenge og containere til vores opgaver, og i boost \u2014 den nyeste version af boost. Udvikleren bruger de klasser, der passer bedst til l\u00f8sning af hans opgaver. <\/p>\n<p>Det hj\u00e6lper ogs\u00e5 i udviklingen med den 'native' implementering af flyttekonstrukt\u00f8rer (<noindex><a rel=\"nofollow\" href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/move_constructor\">move constructors<\/a><\/noindex>) for en r\u00e6kke klasser. Hvis en klasse har en flyttekonstruktor, og denne klasse placeres i en container, s\u00e5 optimerer STL kopieringen af elementer inden for containeren (for eksempel n\u00e5r containeren udvides, og der skal \u00e6ndres capacity og genallokeres hukommelse). <\/p>\n<h3>Et sk\u00e6vt element<\/h3>\n<p>\nDet mest ubehagelige (men ikke kritiske) resultat af migreringen er, at vi har oplevet en stigning i m\u00e6ngden af <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-filer<\/a><\/noindex>, og den samlede build-output med alle mellemfilerne begyndte at fylde 60 \u2013 70 GB. Denne adf\u00e6rd skyldes moderne standardbibliotekers karakteristika, der er blevet mindre kritiske over for m\u00e6ngden af genererede servicefiler. Det p\u00e5virker ikke driften af den kompilerede applikation, men medf\u00f8rer en r\u00e6kke ulemper i udviklingen, is\u00e6r forl\u00e6nger det kompileringstiden. Kravene til ledig plads p\u00e5 disken b\u00e5de p\u00e5 build-servere og udviklernes maskiner er ogs\u00e5 steget. Vores udviklere arbejder parallelt p\u00e5 flere versioner af platformen, og hundredvis af gigabyte mellemfiler kan nogle gange skabe vanskeligheder i arbejdet. Problemet er ubehageligt, men ikke kritisk; vi har indtil videre udskudt l\u00f8sningen. Som en af muligheden for at l\u00f8se det betragter vi teknikken <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Single_Compilation_Unit\">unity build<\/a><\/noindex> (det bruges blandt andet af Google til at udvikle browseren Chrome).<br \/>\n<br \/>Kilde: <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.3 - 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\/da\/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.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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\udd47Hvordan vi oversatte 10 millioner linjer C++ kode til standard C++14 (og bagefter til C++17) | ProHoster","description":"For some time (in the fall of 2016), during the development of the next version of the 1C:Enterprise technology platform, the question arose within the development team about supporting the new standard","canonical_url":"https:\/\/prohoster.info\/da\/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":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/32466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=32466"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/32466\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/24270"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=32466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=32466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=32466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}