Spokój i porządek, ogólny spokój ducha to stany pożądane przez każdego człowieka. Nasze życie w zasadzie wiruje – od negatywnych emocji po euforię i z powrotem.

Jak znaleźć i utrzymać punkt równowagi, aby świat był postrzegany pozytywnie i spokojnie, nic nie irytowało i nie przerażało, a chwila obecna przynosiła inspirację i radość? Czy możliwe jest osiągnięcie trwałego spokoju ducha? Tak, to możliwe! Co więcej, wraz z pokojem przychodzi prawdziwa wolność i proste szczęście do życia.

Ten proste zasady i pracują religijnie. Wystarczy przestać myśleć o tym JAK to zmienić i zacząć je STOSOWAĆ.

1. Przestań pytać: „Dlaczego mnie to spotkało?” Zadaj sobie kolejne pytanie: „Co wielkiego się wydarzyło? Co dobrego może to dla mnie zrobić? Dobro na pewno istnieje, trzeba je tylko zobaczyć. Każdy problem może zamienić się w prawdziwy dar z góry, jeśli uznasz go za szansę, a nie karę lub niesprawiedliwość.

2. Pielęgnuj wdzięczność. Każdego wieczoru zastanów się, za co możesz powiedzieć „dziękuję” w ciągu dnia. Jeśli stracisz spokój ducha, pamiętaj o dobrych rzeczach, które masz i za co możesz być wdzięczny w życiu.

3. Obciąż swoje ciało ćwiczenia fizyczne. Pamiętaj, że mózg najaktywniej produkuje „hormony szczęścia” (endorfiny i enkefaliny) podczas treningu fizycznego. Dlatego jeśli dokuczają Ci problemy, stany lękowe, bezsenność, wyjdź na zewnątrz i spaceruj przez kilka godzin. Szybki krok lub bieg oderwie Cię od smutnych myśli, nasyci mózg tlenem i podniesie poziom pozytywnych hormonów.

4. Przyjmij „wesołą postawę” i pomyśl o szczęśliwej pozie dla siebie. Ciało ma wspaniały sposób na pomoc, gdy chcesz przywrócić spokój ducha. „Zapamięta” uczucie radości, jeśli po prostu wyprostujesz plecy, wyprostujesz ramiona, radośnie przeciągniesz się i uśmiechniesz. Świadomie utrzymuj się w tej pozycji przez chwilę, a zobaczysz, że myśli w Twojej głowie staną się spokojniejsze, pewniejsze i szczęśliwsze.

5. Wróć do stanu „tu i teraz”. Proste ćwiczenie może pomóc pozbyć się niepokoju: rozejrzyj się, skup się na tym, co widzisz. Zacznij w myślach „sondować” obraz, wstawiając jak najwięcej słów „teraz” i „tutaj”. Na przykład: „Idę teraz ulicą, świeci tu słońce. Teraz widzę mężczyznę, on niesie żółte kwiaty…” itd. Życie składa się tylko z chwil „teraz”, nie zapominaj o tym.

6. Nie wyolbrzymiaj swoich problemów. W końcu nawet jeśli zbliżysz muchę do oczu, przybierze ona rozmiar słonia! Jeśli jakieś doświadczenie wydaje Ci się nie do pokonania, pomyśl, jakby minęło już dziesięć lat... Ile problemów miałeś wcześniej - wszystkie rozwiązałeś. Dlatego ten problem minie, nie zanurzaj się w nim na oślep!

7. Śmiej się więcej. Spróbuj znaleźć coś zabawnego w obecnym stanie rzeczy. Jeśli to nie zadziała, po prostu znajdź powód do szczerego śmiechu. Obejrzyj zabawny film, przypomnij sobie zabawne wydarzenie. Siła śmiechu jest po prostu niesamowita! Spokój ducha często powraca po dobrej dawce humoru.

8. Wybaczaj więcej. Urazy są jak ciężkie, cuchnące kamienie, które wszędzie ze sobą nosisz. Jaki spokój ducha można mieć przy takim obciążeniu? Więc nie chowaj urazy. Ludzie są tylko ludźmi, nie mogą być doskonali i zawsze niosą ze sobą tylko dobro. Więc przebacz przestępcom i przebacz sobie.

10. Komunikuj się więcej. Każdy ból ukryty w środku mnoży się i przynosi nowe smutne owoce. Dlatego dziel się swoimi doświadczeniami, rozmawiaj o nich z bliskimi i szukaj ich wsparcia. Nie zapominaj, że człowiek nie jest stworzony do samotności. Spokój ducha można znaleźć tylko w bliskich relacjach - przyjaźni, miłości, rodzinie.

11. Módl się i medytuj. Nie pozwól, aby złe, gniewne myśli kontrolowały Cię i powodowały panikę, ból i irytację. Zamień je na krótkie modlitwy – odwołanie się do Boga lub na medytację – stan niemyślenia. Zatrzymaj niekontrolowany przepływ rozmów między sobą. To podstawa dobrego i stabilnego stanu umysłu.

Kiedy wydaje się, że kolejny poziom został zaliczony, Cienie z pewnością wypełzną i sprawdzą, czy podczas ich tańców zachowana jest równowaga i przytomność umysłu.

Reakcja na Cień kołysze wahadło ego i odkrywa bezlitosną prawdę: równowaga jest napięta jak ostrożność linoskoczka i grozi strąceniem odważnego człowieka w otchłań przeszłości.

Prawdziwa równowaga to brak obsesyjnej obserwacji: szukania tego, że coś tu jest nie tak.

„Wszystko jest jak zwykle” – mówi wewnętrzny kontemplator, nawet jeśli wokół panuje zaraza lub zagrożenie – „tylko ci ludzie są zranieni i muszą zrozumieć swoją drogę”.

Jeśli jednak pojawią się inne reakcje, oznacza to, że ścieżka nie została jeszcze ukończona i zakończenie etapu jest jeszcze przed nami.

- Dlaczego to robię? – Jesteś dopiero na początku swojej podróży przez poziom.
– Jestem gotowy walczyć na śmierć i życie! – Przeszedłeś jedną czwartą drogi.
– Podoba mi się ta przygoda! – połowa drogi już przebyta.
„Przyjdź do mnie, ocalę cię” – przebyłeś już trzy czwarte drogi.
– Jakże jestem ci wdzięczny, że jesteś dokładnie taki jak ty! – Do końca poziomu pozostało 2/10 drogi.
- Podróżniku, dokąd zmierzasz i co chcesz osiągnąć swoją agresją? – Przeszedłeś ten poziom i przystępujesz do egzaminu na groźnego Cienia.

W Cieniu jest dużo miłości i dużo artyzmu. Jak dobra nauczycielka, doskonale odgrywa rolę Tyrana, Ofiary i Wybawcy, aby sprawdzić swoją równowagę. W końcu, mówiąc językiem graczy: RÓWNOWAGA TO BOSKI POZIOM.

©Mark Ifraimov

********

ZASADY SPOKOJU

Bądź gotowy odpuścić.

Ludzie, którzy Cię oszukują, manipulują, obwiniają, narzekają, są nieszczęśliwi, doprowadzają Cię do szaleństwa, pozbawiają Cię emocjonalnego spokoju.

Być równym.

Ta równość, w której każdy jest odpowiedzialny za swoje życie i nie oczekuje, że ktoś go uszczęśliwi i powie, jak ma żyć.

Bądź czujny.

Nie poddawaj się narzekaniu i manipulacji. W związkach chodzi o bycie obecnym w życiu drugiej osoby, a nie o jej ratowanie. Nie mylić z bezpośrednią prośbą o pomoc. Proszą - pomóżcie jak tylko możecie.

Bądź przygotowany na odejście.

Nie daj się wciągnąć w sprzeczki i oskarżenia. Nie rób wymówek. Jeśli się mylisz, przeproś. Wystarczy. Jeśli wyrządziłeś komuś wielką krzywdę, zapytaj, co można zrobić, aby zadośćuczynić? Jeśli nie będzie reakcji, przygotuj się na odejście. Tu już nie chodzi o twoją winę, ale o jego oskarżenia.

Bądź stanowczy.

„Chwalą cię – nie bądź szczęśliwy. Karcą cię - nie denerwuj się” (c). Nie można cały czas wygrywać ani przegrywać. Nie da się nawet podzielić wszystkiego na przegraną i wygraną. Dowiedz się, czego się nauczyłeś i co nowego odkryłeś o sobie dzięki temu wydarzeniu. Idź naprzód swoją własną ścieżką, pewnym krokiem.

Przemijaj.

Przejdź obok konfliktów innych ludzi, plotek, kategoryczności, osądów, złości, zemsty, marudzenia, etykietek, zazdrości. Nie mieszaj się w to wszystko, nie wspieraj, nie marnuj czasu... Idź dalej...

Bądź przygotowany na rozstanie.

Kontynuujemy zapoznawanie się z innowacjami językowymi standardu C++17. W tym artykule przyjrzymy się temu, co nazwałbym kontynuacją nobilitacji języka. Te. Nie zobaczymy tu zupełnie nowych, z funkcjonalnego punktu widzenia, rzeczy – raczej doprowadzenie starej funkcjonalności do bardziej akceptowalnego stanu. Tutaj przyjrzymy się, co zmieniło się w kolejności wykonywania podwyrażeń, jakie pojawiły się nowe gwarancje dotyczące wykluczenia niepotrzebnego kopiowania, a także jakie nowości dodano do lambd.

Uporządkowanie rzeczy

Wielu programistów C++ napotkało „interesujące” problemy, które przedstawiają kontrowersyjny kod i zadaje sobie pytanie: „Co zostanie wypisane?” Jednym z typowych przykładów takiego kodu jest następujący przykład:

Int i = 0; ja = i++ + i++;

Tego rodzaju „inteligentny” kod można znaleźć zarówno w Internecie, jak i podczas wywiadów. Celem takich pytań jest sprawdzenie, na ile osoba udzielająca odpowiedzi zna specyfikę kolejności wykonywania wyrażeń w C++.

Przynajmniej taki jest deklarowany cel. To prawda, uważam, że w większości przypadków osoba zadając takie pytania chce po prostu pogłaskać swoją próżność. Wiedza o tym, co taki kod wyświetli, jest całkowicie niepotrzebna, ponieważ takiego kodu po prostu nie da się napisać. A skoro nie możesz pisać, to po co pytać o to wnioskodawcę? Takie pytania są odpowiednie dla „pokojów dla palących”, w których znani programiści omawiają przypadki Edge; nie nadają się do rozmów kwalifikacyjnych. Polecam przeczytać przemyślenia Raymonda Chena na ten temat: „Czy ludzie z poważną miną piszą szalony kod z wieloma nakładającymi się efektami ubocznymi?”

Ale to przypadek patologiczny, widoczny gołym okiem i jak już wspomniałem, normalny programista nigdy by tak nie napisał. Ale są też przypadki mniej oczywiste, które potrafią napisać nawet doświadczeni programiści. Spójrzmy na ten fragment kodu:

Void f2() ( std::string s = "ale słyszałem, że to działa, nawet jeśli w to nie wierzysz"; s.replace(0, 4, "") .replace(s.find("even" ), 4, "tylko") .replace(s.find("nie"t"), 6, ""); accord(s == "Słyszałem, że to działa tylko wtedy, gdy w to wierzysz"); )

Kod ten jest prezentowany w ostatnia książka Stroustrupa „Język programowania C++, wydanie 4”, w sekcji 36.3.6 i na pierwszy rzut oka wygląda całkiem odpowiedni i poprawny. Ale to tylko na pierwszy rzut oka; w rzeczywistości nie ma gwarancji, że powyższy kod wygeneruje oczekiwany ciąg znaków, a zatem potwierdzenie nie zadziała.

Jak widać nawet twórca C++ popełnił błąd w tak małym fragmencie kodu. Co to znaczy? Po pierwsze, chodzi o to, że nie trzeba wciskać dużej ilości kodu w jedno wyrażenie, w którym dzieje się wiele różnych rzeczy. Pierwsza wersja tego kodu, przedstawiona na tej samej stronie książki, jest znacznie prostsza i lepsza:

Void f() ( std::string s = "ale słyszałem, że to działa, nawet jeśli w to nie wierzysz"; s.replace(0, 4, ""); s.replace(s.find(" parzysty"), 4, "tylko"); s.replace(s.find("nie"t"), 6, "");asser(s == "Słyszałem, że to działa tylko wtedy, gdy w to wierzysz" ); )

Opcja ta jest nie tylko poprawna z punktu widzenia płynności programu, ale jest także łatwiejsza do odczytania. Ale to nie jedyny wniosek, jaki musimy wyciągnąć, jest jeszcze inny, który wysunęli już dla nas autorzy propozycji P0145R3: coś jest nie tak z kolejnością wykonywania podwyrażeń wyrażeń w C++.

Stary porządek

Zanim przejdziemy do samego wniosku i zmian, jakie spowodowało jego przyjęcie, proponuję przypomnieć obowiązujące przepisy. Pomoże to odświeżyć pamięć (i pomóc komuś dowiedzieć się), dlaczego 2 podane wcześniej przykłady są złym kodem C++ (czysto z punktu widzenia języka, a nie estetyki). Zatem w przeciwieństwie do wielu innych języków programowania, w C++ kolejność wykonywania podwyrażeń w wyrażeniach nie jest określona przez standard i jest pozostawiona kompilatorowi. Oczywiście nadal obowiązuje pewien porządek, ale nie będę tutaj opisywać wszystkich szczegółów, bo... jest ich całkiem sporo. Ważne jest, aby zrozumieć, że z reguły 2 podwyrażenia jednego dużego wyrażenia są wykonywane niezależnie od siebie w niepewny kolejności (dużym wyjątkiem od tej reguły jest operator przecinek „,”).

Weźmy na przykład nasz pierwszy przykład: i = i++ + i++; . Duże wyrażenie składa się z 4 małych podwyrażeń: i , i++ , i++ i i++ + i++ . Co gwarantuje standard C++14? Gwarantuje to (expr.ass), że oba wyrażenia i++ zostaną ocenione przed obliczeniem ich sumy, a także, że wyrażenie i zostanie ocenione przed przypisaniem do niego wyniku sumy. Przypominam również, że wyrażenie i++ zwraca starą wartość i, a następnie zwiększa i o jeden (zwiększa je). To z kolei oznacza, że ​​wyrażenie uważa się za obliczone, gdy uzyskana zostanie stara wartość i.

Oznacza to, że kompilator może wybrać kilka sposobów oceny pełnego wyrażenia: nie ma ograniczeń co do tego, kiedy efekt ++ powinien zostać zastosowany do i . W rezultacie możemy uzyskać różne znaczenia w i , co oczywiście nie jest dobre, ponieważ program musi dawać przewidywalne wyniki, które nie podlegają kaprysom kompilatora. Na przykład kolejność może wyglądać następująco:

    Obliczamy pierwsze i, jest ono równe 0.

    Obliczamy drugie i, jest ono równe 0.

    Zapisujemy wynik drugiego przyrostu, otrzymujemy i == 1 .

    Zapisujemy wynik pierwszego przyrostu, otrzymujemy i == 2.

    Obliczamy i po lewej stronie znaku równości.

    Obliczamy sumę: 0 + 0 == 0.

    Wynik sumy zapisujemy w i.

    Zwracamy wynik pełnego wyrażenia, tj. i, które jest równe 0.

Powyższe kroki można wykonać w dowolnej kolejności, która nie narusza gwarancji przewidzianych przez normę, a wynikiem będą różne odpowiedzi.

Nawiasem mówiąc, możesz rozważyć prostszą opcję: i = ++i + i++; . Tutaj od razu widać, że wynik będzie inny w zależności od tego, co zostanie najpierw obliczone ++i lub i++ , ponieważ przy pierwszym wyrażeniu skutki uboczne(zwiększanie i o jeden) następuje przed obliczeniem.

Chociaż druga opcja jest bardziej wizualna, obie dają tzw. wynik niezdefiniowane zachowanie(NP, angielskie niezdefiniowane zachowanie). Wszyscy doświadczeni programiści C++ znają ten termin, ale jest mało prawdopodobne, aby wielu znało wszystkie miejsca w języku C++, w których może wystąpić takie zachowanie. Jest szeroki i wystarczający interesujący temat, co mogłoby być tematem więcej niż jednego artykułu, dlatego nie będę się nad tym szerzej rozwodzić. W zasadzie tak szczegółowa analiza wyrażenia nie była konieczna, gdyż zgodnie ze standardem (intro.execution/p15) naszym wyrażeniem jest NP już dlatego, że w jednym wyrażeniu znajdują się dwa podwyrażenia modyfikujące ten sam obiekt skalarny, a kolejność zmian nie jest zdefiniowana. Dlaczego więc przedstawiłem tę analizę? Próbowałem pokazać dlaczego NP objawia się w oparciu o obowiązujące ograniczenia w wykonywaniu wyrażeń, tj. celem było pokazanie, że przy obecnych przepisach standard nie ma innego wyjścia, jak tylko zarzucić ręce.

Przejdźmy teraz do drugiego przykładu i zobaczmy, co jest w nim nie tak. Aby ułatwić zrozumienie, skrócę ten przykład do tego wyrażenia: s.replace(s.find("parzysty"), 4, "tylko"). Co my tu mamy? Istnieje obiekt s , jest wywołanie funkcji składowej std::string::replace , inna funkcja std::string::find , a także argumenty tych funkcji. Jakie gwarancje daje nam norma? Standard gwarantuje, że argumenty funkcji zostaną ocenione przed wywołaniem funkcji. Zapewnia również, że obiekt, na którym wykonywana jest funkcja, musi zostać oceniony przed wywołaniem funkcji na nim. Wszystko to jest jasne i logiczne. To prawda, że ​​nie mamy innych gwarancji: nie ma gwarancji, że s zostanie obliczone przed obliczeniem argumentów funkcji zamiany, nie ma też żadnej gwarancji co do kolejności obliczania tych samych argumentów. W związku z tym możemy otrzymać następującą kolejność obliczeń: s.find("even") , "only" , 4 , s , s.replace(...) . Lub jakikolwiek inny, który nie narusza wcześniej określonych gwarancji standardu.

Z powyższego tekstu należy wyróżnić 2 główne punkty: 1) wyrażenia po lewej i prawej stronie punktu można oceniać w dowolnej kolejności, 2) argumenty funkcji można oceniać w dowolnej kolejności. Na tej podstawie powinno być teraz jasne, dlaczego kod w książce Stroustrupa jest nieprawidłowy. W wyrażeniu:

S.replace(0, 4, "") .replace(s.find("parzysty"), 4, "tylko") .replace(s.find("nie"t"), 6, "");

Obydwa wywołania find mogą zakończyć się przed wykonaniem poprzednich wywołań zamiany (w kodzie). A może nawet po. Pierwszy może być wcześniej, a drugi później – nie wiadomo, bo… kolejność nie jest określona. W rezultacie ten kod generuje nieprzewidywalne wyniki, chociaż tak nie jest NP. Jednak jak już mówiłem, kompetentny programista nie napisałby takiego kodu, a to, że jest w książce Stroustrupa, nie oznacza, że ​​tak by to napisał – po prostu podał przykład łańcucha wywołań.

Ponadto łańcuch połączeń może nie być tak oczywisty. Na przykład, oto kod:

Std::cout<< first << second;

Jest to także łańcuch wywołań, który może wyglądać następująco:

Std::cout.operator<<(first).operator<<(second);

lub tak:

Operator<<(operator<<(std::cout, first), second);

Różnica nie jest fundamentalna. Jeśli nagle wyrażenia pierwsze i drugie w jakiś sposób odnoszą się do tego samego obiektu i jedno z tych wyrażeń modyfikuje ten obiekt, to istnieje duża szansa, że ​​na wyjściu będzie niestabilny kod lub NP.

Kolejny ciekawy przykład z powyższego zdania:

Std::mapa słownik słownik = słownik.rozmiar();

Tak, kod wygląda na bezsensowny, ale co w rezultacie da? Nawet bezsensowny kod powinien dawać przewidywalne wyniki. Niestety, C++ z 2014 roku tylko wzrusza ramionami – nie wiem, mówią.

Funkcje i operatory

Kiedy przyjrzeliśmy się łańcuchowi wywołań, dotknęliśmy innego interesującego punktu: co właściwie robi wywołanie std::cout?<< first << second; . Как мы уже видели, в зависимости от того, чем являются first и second , мы можем получить либо цепочку вызовов функций-членов, либо же вложенные вызовы свободных функций. Но ведь в изначальном варианте записи у нас есть три выражения и 2 оператора << , у нас нет вообще никаких функций!

Jest mało prawdopodobne, aby ten kod spowodował problemy programistom C++: wszyscy prędzej czy później dowiadujemy się o przeciążaniu operatorów i traktujemy to jako coś oczywistego, ale jest jeden niuans tego przeciążenia. Aby pokazać ten niuans, napiszmy następujący szablon funkcji:

Szablon << "first\n", value++) && (cout << "second\n", value++); }

Tak, szablon nie jest najbardziej przydatny ani niezwykły, ale, jak teraz zobaczymy, ma bardzo charakter orientacyjny. Wywołajmy funkcję sprytnąFun z argumentem int, co utworzy instancję takiej funkcji:

Bool sprytnaFun(int& wartość) ( return (cout<< "first\n", value++) && (cout << "second\n", value++); }

Po wywołaniu tej funkcji gwarantowane jest, że dane wyjściowe będą następujące:

jeśli pierwsza wartość++ zwróci 0 , w przeciwnym razie będzie tak:

Pierwsza sekunda

I nic innego, co jest oczywiste: operator && ma ścisłą gwarancję zwarcie(KZ, angielskie zwarcie) i wykonanie lewej części w prawo. Z drugiej strony, jeśli utworzymy pewien typ Int, dla którego nadpiszemy zarówno operator postfix++, jak i operator&&, a następnie utworzymy za jego pomocą instancję naszego szablonu, otrzymamy następującą funkcję:

Int sprytnyFun(Int&wartość) ( powrót (cout<< "first\n", value.operator++(0)) .operator&&((cout << "second\n", value.operator++(0))); }

Nie zdradziłem, w co zmieni się wywołanie cout, żeby jeszcze bardziej nie zaśmiecać i tak już niezbyt łatwego do odczytania kodu. W oparciu o to, co omówiliśmy do tej pory, nie powinno Cię dziwić, że wynik tego kodu będzie inny niż to, co otrzymasz w przypadku zwykłego int . Tutaj możesz również uzyskać 2 opcje, ale będą one różne:

Pierwsza sekunda

Drugi pierwszy

Oczywiście nie możemy dostać opcji z jednym pierwszym ze względu na to, że zwarcie dla przeciążonych operatorów nie działa. Jeśli przyjrzysz się bliżej temu przykładowi, powinieneś zrozumieć dlaczego: aby wykonać przeciążony operator&&, należy dla niego ocenić argument (czyli pożegnać się z KB), a poza tym KB działa tylko wtedy, gdy wyrażenie po lewej stronie jest wartością bool , co ma miejsce w przypadku przesłoniętego operatora, nie może być. Nie można więc mieć złudzeń co do zwarcia – ono nie istnieje i nie będzie dla przeciążonych operatorów.

No cóż, nie może być zwarcia, więc nie możemy uzyskać pierwszej opcji wyjścia (tylko pierwsza), ale nawet opcja z dwiema liniami wyjściowymi może być inna lub nie! Pomyśl tylko: mamy ten sam kod w szablonie funkcji, który dla niektórych argumentów szablonu jest wykonywany według jednej reguły, a dla innych według zupełnie innych.

Wszystko to dzieje się, ponieważ w C++ 14 gwarancje dla operatorów i ich operandów różnią się w zależności od tego, jakie to są operandy. Zgodnie ze standardem dla typów całkowitych działają wszystkie gwarancje operatorów tak, jak są dla nich opisane w standardzie, natomiast dla operatorów przeciążonych działają już zasady rządzące wywoływaniem funkcji. Te. w przypadku operatorów przeciążonych wyrażenie jest „przepisywane” przez kompilator do łańcucha wywołań funkcji, a następnie stosowane są reguły ze standardu zdefiniowane dla takiego łańcucha. Do operatorów przesłoniętych nie mają zastosowania żadne gwarancje operatorskie wynikające z normy..

Wszystko, co opisano wcześniej, przedstawia bardzo ponury obraz: w C++ panuje zbyt duży chaos, jeśli chodzi o ocenę wyrażeń. Nic dziwnego, że ludzie mają dość znoszenia takich rzeczy, a odwieczne stwierdzenia, że ​​to wszystko jest potrzebne do jakiejś mitycznej optymalizacji i nie należy tego zmieniać, nie są już uważane za wystarczające uzasadnienie. Zwyciężył zdrowy rozsądek i C++ 17 otrzymało kilka zmian w zakresie uporządkowania tego bałaganu. A jakim zmianom będziemy się teraz przyglądać?

Nowe zamówienie

Pierwszą zmianą wprowadzoną przez C++ 17 jest kolejność wykonanie operatory postfiksowe, operatory przypisania i operatory przesunięcia bitowego. Teraz wszystkie operatory postfiksowe, a także operatory przesunięcia bitowego są wykonywane od lewej do prawej, podczas gdy operatory przypisania są wykonywane od prawej do lewej. Przez „wykonane” w tym kontekście mam na myśli, że wyrażenie jest oceniane (tzn. zwracany jest jego wynik) i zatwierdzane są wszystkie związane z nim skutki uboczne.

Aby wyjaśnić kolejność wyrażeń, weźmy przykład ze zdania (w poniższym przykładzie najpierw wykonywane jest wyrażenie a, potem b):

A.b a->b a->*b a(b1, b2, b3) b @= a a[b] a<< b a >>b

Gdzie @ jest dowolnym prawidłowym operatorem w tym kontekście (na przykład +). Zatem w oparciu o nowe zasady przykład podany w książce Stroustrupa o C++ 11 w końcu staje się poprawny w C++ 17 i zawsze będzie dawać poprawny i oczekiwany wynik. Jak widać, nowe zasady nie wpływają na kolejność wykonywania argumentów funkcji względem siebie: nadal można je wykonywać w dowolnej kolejności, ale ich wykonanie nie może się przeplatać. Innymi słowy, są one uporządkowane względem siebie, ale kolejność nie jest regulowana.

Teraz spójrzmy na kilka „ciekawych” przykładów, gdzie w C++ 14 mieliśmy NP, ale w C++ 17 zniknął. Podaję te przykłady wyłącznie na własny użytek, proszę, abyście nie dręczyli nimi ludzi podczas rozmów kwalifikacyjnych.

ja = i++; f(++i, ++i) f(i++, i++) tablica = i++ i<< i++ cout << i++ << i++

Ale te przykłady pozostały NP w nowym standardzie:

I = i++ + i++ i = ++i * i++

Ponieważ nie dodano żadnych reguł regulujących kolejność wykonywania podwyrażeń operatorów arytmetycznych. Ale faktem jest, że Zniknięcie NP z tych przykładów wcale nie oznacza, że ​​czas nasycić swój kod podobnymi - nie. Każdy z tych przykładów wymaga staranności i udowodnienia, że ​​tak nie jest NP. Te. każdy programista, który zobaczy taki kod, będzie zmuszony się zatrzymać, zapamiętać (lub zajrzeć do standardu) i upewnić się, że widzi przed sobą poprawny kod. Kod nie powinien być „inteligentny”, kod powinien być zrozumiały. Co więcej, taka kombinacja wyrażeń w rzeczywistości niewiele daje.

Swoją drogą uważny czytelnik zapewne zauważył cout linii<< i++ << i++ в вышеприведённых примерах, и если он не знает обо всех правилах и поверил автору, то он наверняка воспользовался такой логикой: пример переписывается как

Operator<<(i++).operator<<(i++)

po czym obowiązują nowe zasady dotyczące domeny . , więc nie ma tego w kodzie NP. Takie rozumowanie wydaje się logiczne, ale nie jest do końca poprawne. Tak naprawdę wszystko jest prostsze: przykład jest faktycznie „przepisany” przez kompilator na ten, który podałem, ale kolejność wykonania jest budowana przed przepisaniem! Te. według nowych zasad, przeciążone operatory przestrzegają reguł wykonywania operatorów wbudowanych przynajmniej pod względem kolejności oceniania podwyrażeń. Dlatego opieramy się na fakcie, że lewy operand operatora<< вычисляется до правого у нас и нет NP w kodzie.

Okazuje się, że nie mamy już rozbieżności w kolejności wykonywania wyrażeń dla operatorów wbudowanych i przeciążonych oraz nasz przykład z ostatniej sekcji:

Szablon bool sprytnyFun(wartość T&) ( return (cout<< "first\n", value++) && (cout << "second\n", value++); }

dla dowolnego typu zawsze będzie drukowany jako pierwszy, a następnie jako drugi. Odwrotna kolejność wyników jest obecnie wykluczona przez normę. Jest to oczywiście bardzo ważna innowacja, która pozwala wnioskować o kodzie, który zostanie napisany, a nie o tym, co zostanie z niego wygenerowane. Warto zauważyć, że ta innowacja stworzyła różnicę pomiędzy jawnym i niejawnym wywoływaniem przeciążonego operatora. Spójrzmy na przykład:

#włączać używając przestrzeni nazw std; klasa SomeClass (znajomy operator int<<(const SomeClass& obj, int&); public: SomeClass(int var): m_Var{var} { } private: int m_Var; }; int operator<<(const SomeClass& obj, int& shift) { return obj.m_Var << shift; } int main() { int i = 0; int result = SomeClass{i = 1} << (i = 2); cout << "First result: " << result << "\n"; result = operator<<(SomeClass{i = 1}, i = 2); cout << "Second result: " << result << "\n"; };

Pierwszy wynik z pewnością wyniesie 4, a drugi może wynieść 2 lub 4. Ten przykład dobrze pokazuje różnicę między jawnym i niejawnym wywoływaniem przeciążonego operatora w C++ 17.

Oczywiście wraz z wprowadzeniem nowego porządku pojawiło się wiele różnych złożonych wyrażeń, które dały Nanocząstki z poprzednich standardów są obecnie akceptowalne, ale nie oznacza to, że powinny zacząć pojawiać się masowo w kodzie. To nie powinno się zdarzyć tylko dlatego, że tak jest złożony i należy unikać wszystkiego, co jest trudne do zrozumienia. Ale nowe zasady nie tylko dają nam możliwość wywoływania funkcji takich jak f(i++, i++) bez obawy, że program się zepsuje. Nowe reguły nadają kodowi C++ większą rygoryzm i porządek, dzięki czemu między innymi możemy teraz pisać niezawodny kod z łańcuchem wywołań (jawnych lub ukrytych, nie ma to znaczenia).

Chociaż powiedziałem trochę o kodzie w książce Stroustrupa, nie jestem przeciwnikiem łączenia wywołań, a jeśli spojrzymy na nowoczesny kod napisany przy użyciu języków imperatywnych, zobaczymy, że zawiera on coraz więcej łańcuchów (na przykład LINQ i Task+ContinueWith z C# lub Lodash/podkreślenie i Promise+, a następnie z JS). C++ również zmierza w tym kierunku i wkrótce będziemy mogli zobaczyć analogie powyższych przykładów w postaci Range-v3 i future+then w przyszłych standardach C++. Ale jeszcze przed wydaniem nowych standardów możemy korzystać z różnych bibliotek, których interfejs zachęca do stosowania łańcuchów wywołań.

Ogólnie rzecz biorąc, moim zdaniem zmiana zasad kolejności oceniania wyrażeń jest jedną z najważniejszych innowacji w C++17, którą niewielu zauważy, ponieważ wszystko (lub prawie wszystko) będzie po prostu działać tak, jak powinno powinno działać zgodnie ze zdrowym rozsądkiem. A w standardzie C++ z każdym dniem jest coraz więcej zdrowego rozsądku.

Minimalizowanie kopiowania

Jednym z pierwszych kroków w nauce C++ jest nauczenie się konstruktora kopiującego. W końcu za jego pomocą możesz łatwo określić, co i kiedy jest kopiowane. Te. piszemy własną klasę, dodajemy tam konstruktor kopiujący, w którym za pomocą cout zapisujemy wynik i cieszymy się efektem, na podstawie którego dowiadujemy się, ile kopii tworzymy.

Wraz z pojawieniem się semantyki ruchu sytuacja stała się nieco bardziej skomplikowana, więc aby dopełnić obraz, musisz teraz także utworzyć konstruktor ruchu. Ale dla tej sekcji nie ma to znaczenia, ponieważ… wszystko poniżej dotyczy zarówno kopiowania, jak i przenoszenia.

Na przykład napiszmy ten kod:

#włączać używając przestrzeni nazw std; klasa SomeClass ( public: SomeClass() = domyślna; SomeClass(const SomeClass&) ( cout<< "Copy ctor called.\n"; } }; SomeClass meReturn() { return SomeClass{}; } int main() { auto some = meReturn(); };

Ile razy na ekranie pojawi się fraza „Kopiuj wywołany plik.”, jeśli skompilujesz ten kod na kompilatorze implementującym C++ 14 i uruchomisz program? Zero, jeden, a może dwa razy? Prawidłowa odpowiedź: nieznana.

Ci, dla których odpowiedź była zaskoczeniem, zasługują na wyjaśnienie, do którego teraz przejdziemy. Na początek rozpakujmy standard i zastanówmy się, jaka jest tutaj maksymalna liczba kopii Może bądź kreatywny. Największa liczba możliwych kopii wynosi tutaj 2: pierwsza kopia jest tworzona podczas wykonywania instrukcji return, a druga podczas konstruowania obiektu Some. Ale jeśli uruchomisz ten kod na mniej lub bardziej nowoczesnym kompilatorze (bez dodatkowych przełączników!), prawdopodobnie nie zobaczysz podwójnych wyników; bardziej prawdopodobny wynik to albo jedna linia, albo żaden wynik. Teraz zmodyfikujmy nieco kod naszej funkcji, będzie to druga opcja:

SomeClass meReturn() ( SomeClass Some(); zwróć część; )

Jeśli uruchomimy ten kod na popularnych kompilatorach, dane wyjściowe mogą się zmienić lub nie (zmieni się w MSVC 2017, w trybie debugowania). Na koniec jeszcze trochę zmienimy kod funkcji, tylko tym razem na pewno zmieni się wynik (w stosunku do pierwszej opcji i biorąc pod uwagę aktualny stan rzeczy z kompilatorami):

SomeClass meReturn() ( SomeClass Some(); if (false) return SomeClass(); zwróć część; )

Zatem funkcja jest zasadniczo taka sama we wszystkich wariantach, ale zachowanie jest inne – o co tutaj chodzi? Zacząć od nowa. Zgodnie ze standardem C++ w niektórych przypadkach kompilator może nie skopiować obiektu; ta sytuacja nazywa się kopiuj pomiń(PC, elizja kopii angielskiej). Pełną listę (raczej krótką) znaków, które można wykorzystać do określenia, czy dozwolone jest pomijanie kopiowania, opisano w class.copy/p31. Nas interesują dwie podobne, choć wciąż różne sytuacje.

W oryginalnym przykładzie nasza funkcja zwraca wartość tymczasową bezimienny obiekt. W takiej sytuacji kompilator ma prawo pominąć obie kopie i po prostu utworzyć obiekt bezpośrednio w jakimś pliku . Sytuację tę popularnie nazywa się optymalizacja wartości zwrotu(OVZ, optymalizacja wartości zwracanej w języku angielskim). Jeśli spojrzymy na gcc/clang/MSVC, zobaczymy, że dla takiej funkcji pozbywają się obu kopii, w związku z czym dane wyjściowe będą puste.

Tego rodzaju optymalizacja jest dozwolona nie tylko dla return , ale także dla innych miejsc, w których następuje inicjalizacja tymczasowym, bezimienny obiekt. Jeśli więc masz funkcję void meAccept(SomeClass) o nazwie meAccept(SomeClass()) , wówczas kompilator ma prawo pominąć zbędne kopiowanie.

Przejdźmy teraz do drugiej opcji, w której stworzyliśmy o imieniu obiekt na stosie. Dane wyjściowe dla gcc/clang nie uległy zmianie, ale dla MSVC (w trybie debugowania) na wyjściu pojawiła się jedna linia, oczywiste jest, że w tym przypadku MSVC pozbył się tylko drugiej kopii. Na podstawie powyższego staje się jasne, że kompilator również korzysta z komputera PC, ale tutaj dzieje się to według nieco innego kryterium: ma prawo pozbyć się kopiowania o imieniu obiekt na stosie zwracany przez funkcję. Ten rodzaj optymalizacji jest popularnie nazywany nazwana optymalizacja wartości zwracanej(OIVZ, angielska nazwa optymalizacji wartości zwracanej).

Ten rodzaj optymalizacji jest trudniejszy do wykonania dla kompilatora, co widzimy w trzeciej opcji, gdzie dodaliśmy absolutnie bezużyteczne if , co zmusiło wszystkie trzy główne kompilatory do poddania się i wykonania kopii. Zatem OIVZ jest bardziej delikatną optymalizacją niż zwykła OIV i z reguły jest wyłączona, gdy w kodzie znajduje się kilka różnych zwrotów. Jest to jeden z powodów, dla których funkcja powinna mieć tylko jeden zwrot (nie mogę powiedzieć, że argument jest bardzo przekonujący).

Ciekawostką jest to, że powyższa optymalizacja jest stosowana w kompilatorach nawet wtedy, gdy kompilujemy z wyłączoną optymalizacją (-O0, /Od). Co więcej, tylko gcc i clang można zmusić do utworzenia wszystkich kopii. Aby to zrobić, musisz użyć przełącznika -fno-elide-constructors i pod żadnym pozorem MSVC nie utworzy dwóch kopii, a nie ma żadnych [publicznych] przełączników, które mogłyby wyłączyć to zachowanie.

Warto wspomnieć o jeszcze jednej kwestii. Chociaż w C++14 kompilator może usunąć obie kopie, w ten sposób nie wykonując ani razu konstruktora kopiującego, musi zgłosić błąd kompilacji, jeśli nie ma takiego konstruktora. Te. jeśli zamiast istniejącego konstruktora kopiującego napiszemy to: SomeClass(const SomeClass&) = usuń, to program nie zostanie zbudowany nawet wtedy, gdy kompilatory będą mogły całkiem legalnie pozbyć się kopiowania - musi jeszcze istnieć konstruktor.

I wreszcie trzeci punkt: ruch. Jeśli kompilator może pominąć kopiowanie, może pominąć przenoszenie. Te. pod tym względem są całkowicie równoważne. Nawiasem mówiąc, w tym względzie mamy do czynienia z interesującą sytuacją. Wielu programistów (o wielu wnioskuję na podstawie kodu, który widziałem w Internecie) nie do końca rozumie semantykę przenoszenia i pisze kod podobny do tego: return std::move(someObject) . Kod wygląda całkowicie nieszkodliwie i działa zgodnie z oczekiwaniami osoby, która go napisała, ale taki jest kod gwarantowane wyłącza OIVZ. Jak myślisz, co jest lepsze: wykonanie jednego taniego konstruktora ruchów czy niewykonanie niczego?

Nowa rzeczywistość

Teraz czas przyjrzeć się temu, co zmieniło się w C++ 17 w odniesieniu do komputerów PC. Wszystkie zmiany, które omówimy w tej sekcji, są częścią oryginalnej propozycji P0135R1. Jeśli zajrzysz do tego dokumentu, zobaczysz, że opisuje on liczne zmiany w standardzie w zakresie kategorii wyrażeń (głównie wartość), a także różne edycje wyjaśniające, gdzie wyraźnie wykonać bezpośredni(bezpośrednio-) i biurowy Inicjalizacja (kopiowania). Z całego zestawu interesuje nas tylko jedna zmiana, która jest opisana w stmt.return/p2.

Zatem zgodnie z powyższą innowacją zwrócenie przez funkcję tymczasowego nienazwanego obiektu (prvalue) tego samego typu (tzn. nie wymaga konwersji) co typ zwracany przez funkcję powoduje inicjalizację kopii wyniku (co zgodnie z dcl.init/ p(17.6.1), pozwala pominąć kopiowanie). To, co jest napisane w powyższym zdaniu, to w istocie ten sam HIA, tylko tym razem obowiązkowy. Te. jeśli kompilatorem jest C++ 14 mógł w tym przypadku pozbądź się kopiowania/przenoszenia, to teraz musieć Zrób to. Co nam to daje, skoro widzieliśmy już, że sam kompilator radzi sobie znakomicie? A to daje nam co następuje, mając następujący kod:

SomeClass meReturn() (zwróć SomeClass(); )

Nie możemy w ogóle kopiować i przenosić konstruktorów, a mimo to będzie on się kompilował. Warto zwrócić uwagę, że zmienił się jedynie przypadek, gdy z tymczasowego bezimiennego obiektu zostanie utworzony kolejny obiekt, jednak jeśli zwrócimy nazwany obiekt (OIVZ), to nawet jeśli kompilator będzie mógł pominąć kopiowanie, obecność odpowiedniego konstruktora jest obowiązkowa .

Jest jeszcze jeden punkt, który jest już związany z przekazywaniem argumentów, a nie wartością zwracaną. Jeśli mamy taki kod:

Anuluj mnieAkceptuj([] SomeClass s) ( )

Wtedy przy wywołaniu funkcji meAccept(SomeClass()) również nie będzie kopiowania i to znowu nie jest już optymalizacja, ale wymóg standardu. Wynika to ze zmian w definicji prvalue (basic.lval) i tego, co ta zmiana pociąga za sobą. Przyjrzyjmy się tej linii: meAccept(SomeClass()) . W starym rozumieniu wartości, SomeClass() jest obiektem tymczasowym, który jest następnie kopiowany do parametru funkcji. Ale nowa definicja prvalue jest taka, że ​​już nią nie jest obiekt, Ale wyrażenie, którego ocena jest inicjalizacją obiektu. Co to oznacza dla nas? Oznacza to, że w rozważanym wyrażeniu SomeClass() nie jest obiektem tymczasowym, ale wyrażeniem inicjującym parametr funkcji. Tutaj włączona jest wspomniana wcześniej reguła opisana w dcl.init/p(17.6.1) i nie następuje żadne kopiowanie - inicjalizacja odbywa się bezpośrednio.

Na pierwszy rzut oka jest to dość nieistotna innowacja, bo to samo działo się wcześniej, tyle że kompilatory nie były do ​​tego zobowiązane. Jednak ta innowacja zmieniła samą istotę koncepcji prvalue, dlatego nie należy jej uważać za nieistotną. A z czysto praktycznego punktu widzenia trzeba o tej zmianie wiedzieć, bo studiując język, uczymy się go empirycznie, a w tym procesie bardzo częste są eksperymenty z konstruktorami kopiuj/przenieś. Zatem począwszy od C++17 nie można w żaden sposób zmusić kompilatora do wykonania kopii w opisanych wcześniej przykładach. Żadne flagi nie pomogą, jeśli program jest skompilowany dla C++ 17, a kompilator faktycznie go obsługuje. Jeśli chodzi o kod używany na co dzień, ta innowacja umożliwia tworzenie funkcji fabrycznych, które zwracają obiekty, które nie mają konstruktorów kopiujących/przenoszących. Jak bardzo jest to konieczne? Czas pokaże.

Lambdy

Komitet nadal okazuje lambdom swoją miłość, dodając do nich coś nowego w każdym nowym wydaniu standardu. Rok 2017 nie był wyjątkiem, a lambdy otrzymały swoją część innowacji. Chociaż nadal czekam na krótką składnię (jak x => x w C#) i uważam, że innowacje tego standardu są nieistotne, nadal nie mogę ich zignorować.

Uchwycenie tego

A więc pierwsza innowacja. Możesz teraz przekazać kopię obiektu do listy przechwytywania za pomocą wskaźnika this. Przed C++17, jeśli chcieliśmy przekazać kopię bieżącego obiektu do lambdy, byliśmy zmuszeni napisać coś takiego:

#włączać używając przestrzeni nazw std; klasa SomeClass ( public: SomeClass(wartość_t): m_Value(wartość) ( ​​) void SomeMethod() ( auto lambda = [_this = *this] ( for(size_t i = 0; i< _this.m_Value; ++i) cout << "This is lambda!!!\n"; }; lambda(); } private: size_t m_Value; }; int main() { SomeClass some{3}; some.someMethod(); };

Główną wadą tego podejścia jest konieczność jawnego określenia nazwy obiektu, do którego *to skopiowaliśmy za każdym razem, gdy uzyskujemy do niego dostęp. C++ 17 naprawia tę wadę, umożliwiając pisanie w ten sposób:

Auto lambda = [*this] ( for(size_t i = 0; tj< m_Value; ++i) cout << "This is lambda!!!\n"; };

Te. dostęp do składowych obiektu odbywa się dokładnie tak samo jak gdybyśmy tworzyli lambdę z taką listą przechwytywania, tyle że w tym przypadku nie do bieżącego obiektu (czyli wskaźnika this), lecz jego kopia przekazywana jest do lambda. Zaznaczam, że nie musiałem pisać takiego kodu, więc trudno mi ocenić przydatność innowacji, ale na pewno komuś ułatwi to życie. Mogę się tylko nimi cieszyć i przejść do kolejnej innowacji.

Potrzebujesz więcej spójności!

Kolejną zmianą, która była już dawno oczekiwana, jest dodanie możliwości używania lambd w wyrażeniach stałych. Oczywiście takie lambdy również muszą być stałe. Na przykład:

Auto jedenaście = (zwróć 11; ); szyk arr;

Jak widać, w definicji lambdy nic się nie zmieniło, ale jej wywołanie jest używane w kontekście, w którym obowiązkowe jest użycie stałej czasowej kompilacji. Ponieważ Ten kod kompiluje się pomyślnie, każdy uważny programista może wyciągnąć następujący wniosek: operator() klasy wygenerowanej z lambdy jest członkiem constexpr i ten wniosek jest niewątpliwie poprawny. Od C++ 17 wszystkie wyrażenia lambda są domyślnie constexpr, podczas gdy przed C++ 17 były to po prostu const. Zostaną one jednak zdegradowane do const, jeśli treść funkcji lambda nie spełnia przynajmniej jednego kryterium, któremu podlegają wszystkie funkcje constexpr (kryteria są opisane w dcl.constexpr ). Wprowadźmy minimalną zmianę w naszym kodzie, a lambda nie będzie już constexpr:

Auto jedenaście = ( int x; return 11; );

Przy takiej lambdzie kod tworzący tablicę zwróci błąd kompilacji (a tego właśnie chcieliśmy), ale samo utworzenie lambdy nie spowoduje błędu. Możemy jednak dokręcić śruby i wymagać, aby lambda miała korpus zgodny z powyższymi zasadami:

Auto jedenaście = () constexpr ( int x; return 11; );

Zauważ, że musieliśmy dodać zarówno oczywiste constexpr, jak i () , które nie niosą ze sobą żadnego obciążenia funkcjonalnego i służą jedynie kaprysom standardu. W ten sposób możemy stworzyć funkcje lambda, które z pewnością będą przydatne w kontekście constexpr.

Ta zmiana była oczekiwana od dawna i nie powinna nikogo dziwić: proste funkcje mogą być constexpr , funkcje składowe też mogą, dlaczego lambdy są gorsze? Jak potrzebne są lambdy constexpr? To jest bardziej interesujące pytanie. Myślę, że kod constexpr potrzebuje ich tak samo, jak potrzebuje ich prosty kod. W C++ mamy obecnie do czynienia z boomem na constexpr, a ludzie rywalizują o to, kto może najdalej posunąć się w przenoszeniu pracy ze środowiska wykonawczego do czasu kompilacji.

Posuwają się nawet do napisania parsera JSON, a nawet wykonywania wyrażeń regularnych (dla zainteresowanych obejrzyj wideo z CppCon2017: „constexpr WSZYSTKIE rzeczy!”). Ponadto coraz więcej standardowych (i nie tak standardowych) algorytmów staje się constexpr , co powoduje najbardziej oczywiste użycie lambd, ponieważ są one po prostu tworzone dla algorytmów. Dlatego też moim zdaniem dodanie constexpr jest dobrym krokiem naprzód, który pozwoli na napisanie większej ilości kodu, który będzie wykonywany w czasie kompilacji.

Z drugiej strony, czy naprawdę musimy tak bardzo przechodzić do etapu kompilacji? Oczywiście, gdy coś można przenieść z wielokrotnego wykonywania dynamicznego do pojedynczego wykonania w czasie kompilacji, jest to zdecydowana zaleta. Albo nie? To zależy od zadania i korzyści jakie otrzymamy podczas jego realizacji. Napiszmy parser JSON, który zużywa dużo pamięci RAM i wydłuża czas kompilacji (spójrz przynajmniej na ostatnie 3 minuty powyższego filmu), co nam to daje? Tak, teraz możemy przeanalizować konfigurację w czasie kompilacji i użyć jej w kodzie. Mogliśmy to jednak zrobić wcześniej, bez użycia JSON, a obciążenie w czasie wykonywania byłoby zerowe (na przykład tylko zestaw flag w nagłówku). Przypomina mi to brodaty żart:

Spotyka się dwóch przyjaciół:

– Słyszałem, że kupiłeś samochód?

- Tak! I jak żyłem! Teraz mam czas na wszystko! Wczoraj w ciągu jednego dnia udało mi się wymienić olej, kupić nowe opony, pojechałem na giełdę samochodową kupić błotniki, od razu pojechałem do serwisu samochodowego i je wymieniłem, a także pojechałem do sklepu po płyn niezamarzający. Jak mogłem to wszystko zrobić bez samochodu?!

Ludzie mogą mi się sprzeciwić, że JSON jest wygodniejszy. Niech tak będzie. Następnie dodajmy skrypt w Pythonie (lub nawet CMake), który wygeneruje dla nas obiekt konfiguracyjny z JSON. Tak, będziemy musieli dodać jeszcze jeden krok do zbudowania naszego projektu, ale czy jest to trudniejsze niż napisanie kodu C++, który analizuje JSON? I nikt nie anulował czasu kompilacji (i myślę, że ten powód jest znacznie ważniejszy): jeśli kompilacja kodu zajmie dużo czasu, rozwój zamieni się w piekło. Dlatego nie widzę absolutnie żadnego sensu w przenoszeniu skomplikowanych rzeczy na szyny constexpr. Moim zdaniem jest to niepotrzebna komplikacja, którą można pokazywać na konferencjach, ale w prawdziwym kodzie jest zupełnie niepotrzebna. Stosowanie obliczeń w czasie kompilacji powinno być uzasadnione, a nie tylko dlatego, że „możemy teraz!”

Ostatnie dwa akapity mogą dać błędne wyobrażenie o moim stosunku do tej innowacji: nie jestem przeciwny, jestem po prostu przeciwny wbijaniu gwoździ pod mikroskopem i tyle. Przykład tego ostatniego widać wyraźnie na filmie z CppConu, ale samo pojawienie się lambd constexpr to z pewnością dobra wiadomość, ponieważ lambdy funkcjonalnie nie powinny niczym różnić się od zwykłych funkcji - powinny mieć wszystkie te same możliwości, a jeśli moja pamięć zawiedzie, pozostaje tylko jedna rzecz do dodania: nazwane parametry szablonu dla lambd. Czy spodziewamy się ich w C++ 20?

W każdej niezrozumiałej sytuacji uspokój się, połóż się, przytul, idź zjeść coś pysznego. Uważaj na nerwy :)

Zostaw błędy przeszłości.

Doceń teraźniejszość.

Uśmiechnij się do przyszłości)

Gdy tylko odpuścisz sytuację, która cię dręczy, sytuacja natychmiast cię opuści.




Nie trać panowania nad sobą. Nie wiadomo, co może się wydarzyć pod twoją nieobecność.

Idź do drzewa. Niech nauczy Cię spokoju.

- Jaki jest sekret Twojego spokoju?

„W całkowitej akceptacji tego, co nieuniknione” – odpowiedział Mistrz.

Uporządkuj swoje myśli - a zobaczysz świat innymi oczami.

Nie zapomnij oczyścić swojego serca.

Czym jest pokój?

Żadnych niepotrzebnych myśli.

A jakie myśli są niepotrzebne?

(Wei De-Han)

Twoim najważniejszym skarbem jest pokój w Twojej duszy.

Rumianek działa uspokajająco.

Kontroluj swój nastrój, bo jeśli nie jest posłuszny, rozkazuje.


Spokój można odnaleźć jedynie będąc obserwatorem, spokojnie przyglądającym się ulotnemu biegowi życia. Irwina Yaloma



Spokój jest silniejszy niż emocje.

Cisza jest głośniejsza niż krzyk.

I bez względu na to, co Ci się przydarzy, nie bierz niczego do serca. Niewiele rzeczy na świecie pozostaje ważnych na długo.

Erich Maria Remarque „Łuk Triumfalny” ---

Jeśli złapie Cię deszcz, możesz wyciągnąć z niego pożyteczną lekcję. Jeśli niespodziewanie zacznie padać deszcz, nie chcesz zmoknąć, więc biegniesz ulicą w stronę swojego domu. Ale kiedy docierasz do domu, zauważasz, że nadal jesteś mokry. Jeśli od początku postanowisz nie przyspieszać, zmokniesz, ale nie będziesz się denerwować. To samo należy zrobić w innych podobnych okolicznościach.

Yamamoto Tsunetomo-Hagakure. Książka Samuraj



Jutro będzie tak, jak powinno

i nie stanie się nic, co nie powinno się wydarzyć -

nie przejmuj się.

Jeśli nie ma w nas spokoju, nie ma sensu szukać go na zewnątrz.

Nieobciążony zmartwieniami -
cieszy się życiem.
Nie jest szczęśliwy, gdy go znajdzie,
kiedy przegrywa, nie jest smutny, bo wie
że los nie jest stały.
Kiedy nie jesteśmy związani rzeczami,
Spokój jest w pełni doświadczany.
Jeśli ciało nie odpoczywa od napięcia,
to się zużywa.
Jeśli duch zawsze jest w zmartwieniach,
on zanika.

Chuang Tzu ---

Jeśli rzucisz psu kij, ten spojrzy na kij. A jeśli rzucisz kij lwu, on, nie podnosząc wzroku, spojrzy na rzucającego. Jest to formalne zdanie, które zostało wypowiedziane podczas debat w starożytnych Chinach, jeśli rozmówca zaczął trzymać się słów i przestał widzieć najważniejsze.

Wdychając uspokajam swoje ciało i umysł.
Wydychając, uśmiecham się.
Będąc w chwili obecnej wiem, że ta chwila jest niesamowita!

Pozwól sobie na głębokie oddychanie i nie narzucaj sobie ograniczeń.

Siła należy do tych, którzy wierzą we własną siłę.

Rozwiń w sobie nawyk monitorowania swojego stanu mentalno-emocjonalnego poprzez samoobserwację. Dobrze jest regularnie zadawać sobie pytanie: „Czy w tej chwili jestem spokojny?” to pytanie, które warto sobie regularnie zadawać. Możesz także zapytać: „Co się we mnie w tej chwili dzieje?”

Eckharta Tolle’a

Wolność to wolność od zmartwień. Kiedy już zrozumiesz, że nie możesz wpływać na wyniki, zignoruj ​​swoje pragnienia i obawy. Niech przychodzą i odchodzą. Nie karm ich zainteresowaniem i uwagą. W rzeczywistości wszystko dzieje się tobie, a nie przez ciebie.

Nisargadatta Maharaj


Im spokojniejsza i bardziej zrównoważona jest osoba, tym potężniejszy jest jej potencjał i tym większy będzie jego sukces w dobrych i godnych czynach. Zrównoważony umysł jest jednym z największych skarbów mądrości.


Podstawą wszelkiej mądrości jest spokój i cierpliwość.

Przestań się martwić, a wtedy będziesz mógł zobaczyć wspaniały wzór...

Kiedy umysł osiąga spokój, zaczynasz doceniać światło księżyca i podmuch wiatru i rozumiesz, że nie ma potrzeby zgiełku świata.

Znajdź spokój w swojej duszy, a tysiące wokół ciebie zostaną zbawione.

Tak naprawdę pragniesz jedynie pokoju i miłości. Od nich wyszedłeś, do nich wrócisz i jesteś nimi. Papadżi


Najpiękniejsi i zdrowi ludzie to ludzie, których nic nie drażni.


Najwyższym stopniem ludzkiej mądrości jest umiejętność zachowania spokoju pomimo zewnętrznych burz.



Nie jesteś związany swoimi doświadczeniami, ale faktem, że się ich trzymasz.

Nie podejmuj pochopnych decyzji. Dobrze rozważ wszystkie za i przeciw. Prawie każdy człowiek ma niebiańskiego przewodnika, drugie ja. Pomyśl i zapytaj go, czy warto zrobić to, co zaplanowałeś, czy nie?! Naucz się obserwować, widzieć niewidzialne, przewidywać sytuacje.

Kiedy kontemplujesz górskie lasy i strumienie płynące po kamieniach, twoje serce, zamglone ziemskim brudem, stopniowo się rozjaśnia. Kiedy czytasz starożytne kanony i patrzysz na obrazy starożytnych mistrzów, duch światowej wulgarności stopniowo zanika. Hong Zichen, Smak korzeni.


Mądrość wiąże się ze zdolnością do zachowania spokoju. Po prostu patrz i słuchaj. Nic więcej nie jest potrzebne. Kiedy jesteś spokojny, kiedy po prostu patrzysz i słuchasz, aktywuje się w tobie inteligencja wolna od koncepcji. Niech pokój kieruje waszymi słowami i czynami.

Eckharta Tolle’a


Nigdy nie osiągniemy pokoju w świecie zewnętrznym, dopóki nie osiągniemy go w świecie wewnętrznym.

Istotą równowagi nie jest lgnięcie.

Istotą relaksu nie jest trzymanie się.

Istotą naturalności jest brak wysiłku.

Ten, kto nie jest zazdrosny i nie życzy nikomu krzywdy, osiągnął równowagę. Dla niego cały świat jest pełen szczęścia.

Aby życie na nowo rozkwitło, kipiało i było przepełnione ekscytującą radością i szczęściem, wystarczy się zatrzymać... Zatrzymać i pozwolić sobie roztopić się w przyjemnościach...

Nie martw się o swoją przyszłość, bądź spokojny teraz, a wszystko się ułoży.

Jeśli woda nie jest zmętniona, osiada sama. Jeżeli lustro nie jest zabrudzone, samo będzie odbijało światło. Serca ludzkiego nie można oczyścić własną wolą. Wyeliminuj to, co je zanieczyszcza, a jego czystość się objawi. Nie musisz szukać radości poza sobą. Wyeliminuj to, co Cię niepokoi, a radość automatycznie zapanuje w Twojej duszy.


Czasem po prostu zostaw to w spokoju...

W środku huraganu zawsze jest cicho. Bądź tym cichym miejscem w centrum, nawet jeśli wokół szaleją burze.

Jesteś niebem. Wszystko inne to tylko pogoda.

Tylko w spokojnych wodach wszystko odbija się bez zniekształceń.

Tylko spokojna świadomość jest odpowiednia do postrzegania świata.

Jeśli nie wiesz, co robić, poczekaj chwilę. Ukrywać. Żyj tak, jak żyjesz. Znak pojawi się prędzej czy później. Najważniejsze to wiedzieć, że czekasz i być gotowym stawić czoła temu, na co czekasz. Luisa Rivery

Nie martw się o swoją przyszłość, bądź spokojny teraz, a wszystko się ułoży.


Spokój pozbawia wrogów siły. W spokoju nie ma strachu ani nadmiernej złości – jest tylko rzeczywistość, oczyszczona z zniekształceń i zakłóceń wywołanych wybuchami emocji. Kiedy jesteś spokojny, jesteś naprawdę silny.

Dlatego twoi przeciwnicy zawsze będą się starali ze wszystkich sił wyprowadzić cię z tego stanu - zaszczepić strach, zasiać wątpliwości, wywołać złość. Stan wewnętrzny jest bezpośrednio związany z oddychaniem. Bez względu na to, w jakiej sytuacji się znajdziesz, natychmiast uspokój swój oddech, a potem uspokoi się także twój duch.


Najważniejszą rzeczą w życiu duchowym jest zachowanie spokoju serca.

Trzeba zaufać życiu.
Musimy bez lęku zawierzyć się jego przepływowi, bo życie jest od nas nieskończenie mądrzejsze.
Nadal będzie Cię traktowała na swój sposób, czasami dość surowo,
ale w końcu zrozumiesz, że miała rację.

Bądź teraz spokojny, a wszystko się ułoży.

Twój duch nie powinien być wzburzony, żadne złe słowo nie powinno wychodzić z twoich ust; musicie pozostać życzliwi, z sercem pełnym miłości i nie kryjącym w sobie żadnej ukrytej złośliwości; a nawet złoczyńców musicie objąć miłosnymi myślami, hojnymi myślami, głębokimi i bezgranicznymi, oczyszczonymi z wszelkiej złości i nienawiści. Tak właśnie powinniście postępować, moi uczniowie.

Tylko spokojna woda prawidłowo odzwierciedla niebo.

Najlepszym wskaźnikiem poziomu świadomości jest umiejętność spokojnego odniesienia się do trudności życiowych.

Ciągną nieprzytomną osobę w dół, podczas gdy świadoma osoba podnosi się coraz bardziej.

Eckharta Tolle’a.


Usiądź cicho, a zrozumiesz, jak wybredne są codzienne zmartwienia. Ucisz się na chwilę, a zrozumiesz, jak pusta jest codzienna mowa. Porzuć codzienne obowiązki, a zrozumiesz, ile energii ludzie na próżno marnują. Chen Jiru.


Spokój pomaga nam znaleźć wyjście z najtrudniejszych sytuacji.

Skończyła Ci się cierpliwość?...Nadmuchaj ponownie!)

3 spokojne sekundy

Wystarczy spokojnie pomyśleć przez trzy sekundy, żeby wszystko zrozumieć.

Ale gdzie mogę je zdobyć, te naprawdę trzy spokojne sekundy? Jesteśmy zbyt podekscytowani własnymi fantazjami, aby zatrzymać się choćby na chwilę.


Czy widziałeś kiedyś dąb w stanie stresu, delfina w ponurym nastroju, żabę cierpiącą na niską samoocenę, kota, który nie może się zrelaksować, lub ptaka obarczonego urazą? Ucz się od nich umiejętności pogodzenia się z teraźniejszością.
Eckharta Tolle’a

Nie spiesz się. Każdy pączek kwitnie w swoim czasie. Nie zmuszaj pąka, aby stał się kwiatem. Nie zginaj płatków. Są delikatne; skrzywdzisz ich. Poczekaj, a same się otworzą. Sri Sri Ravi Shankar

Nie czcijcie brodatego mężczyzny w niebie ani bożka z księgi. Czcij wdech i wydech, zimowy wiatr muskający twoją twarz, poranny tłum ludzi w metrze, po prostu poczucie, że żyjesz, nigdy nie wiedząc, co nadejdzie.Zauważ Boga w oczach obcego człowieka, Opatrzność w złamanym i zwyczajnym. Czcij ziemię, na której stoisz. Spraw, aby każdy dzień był tańcem, ze łzami w oczach, kontemplując w każdej chwili boskość, dostrzegaj absolut we wszystkim, co względne, i pozwól, aby ludzie nazywali Cię szaleńcem. Niech się śmieją i żartują.

Jeffa Fostera

Najwyższa moc nie polega na zdolności do podbijania innych, ale na zdolności do zjednoczenia się z innymi.

Sri Chinmoy’a

Spróbuj, przynajmniej w niewielkim stopniu, nie wprowadzać umysłu.
Spójrz na świat - po prostu spójrz.
Nie mów „lubię” i „nie lubię”. Nic nie mów.
Nie wypowiadaj słów, po prostu patrz.
Umysł będzie czuł się niekomfortowo.
Umysł chciałby coś powiedzieć.
Po prostu mówisz do umysłu:
„Uspokój się, daj mi zobaczyć, po prostu popatrzę”…

6 mądrych wskazówek od Chen Jiru

1. Usiądź cicho, a zrozumiesz, jak wybredne są codzienne zmartwienia.
2. Milcz przez chwilę, a zrozumiesz, jak pusta jest codzienna mowa.
3. Porzuć codzienne obowiązki, a zrozumiesz, ile energii ludzie na próżno marnują.
4. Zamknij swoje bramy, a zrozumiesz, jak uciążliwe są więzy znajomości.
5. Miej niewiele pragnień, a zrozumiesz, dlaczego jest tak wiele chorób rasy ludzkiej.
6. Bądź bardziej humanitarny, a zrozumiesz, jak bezduszni są zwykli ludzie.

Uwolnij swój umysł od myśli.
Pozwól swojemu sercu się uspokoić.
Spokojnie podążaj za zgiełkiem świata,
Zobacz jak wszystko układa się na swoim miejscu...

Szczęśliwą osobę bardzo łatwo rozpoznać. Zdaje się emanować aurą spokoju i ciepła, porusza się powoli, ale wszędzie udaje się dotrzeć, mówi spokojnie, ale wszyscy go rozumieją. Sekret szczęśliwych ludzi jest prosty – brak napięcia.

Jeśli siedzisz gdzieś w Himalajach i otacza cię cisza, jest to cisza Himalajów, nie twoja. Musisz znaleźć swoje własne Himalaje w zasięgu...

Rany zadane myślami goją się dłużej niż jakiekolwiek inne.

J.K. Rowling, „Harry Potter i Zakon Feniksa”

Mądrość wiąże się ze zdolnością do zachowania spokoju.Po prostu patrz i słuchaj. Nic więcej nie jest potrzebne. Kiedy jesteś spokojny, kiedy po prostu patrzysz i słuchasz, aktywuje się w tobie inteligencja wolna od koncepcji. Niech pokój kieruje waszymi słowami i czynami.

Eckhart Tolle „Co mówi cisza”

Im spokojniejsza i bardziej zrównoważona jest osoba, tym potężniejszy jest jej potencjał i tym większy będzie jego sukces w dobrych i godnych czynach. Zrównoważony umysł jest jednym z największych skarbów mądrości.

Jamesa Allena

Żyjąc w zgodzie ze sobą, potrafisz dogadać się z innymi.

Mądrość Wschodu -

Siedzisz i siedzisz dla siebie; idź - i idź sam.
Najważniejsze, żeby nie robić zamieszania na próżno.

Zmień swoje nastawienie do rzeczy, które Cię niepokoją, a będziesz od nich bezpieczny. (Marek Aureliusz)

Skieruj swoją uwagę na splot słoneczny. Spróbuj wyobrazić sobie, że w Twoim wnętrzu zapala się mała kula słońca. Pozwól mu rozbłysnąć, stać się większym i silniejszym. Niech jego promienie cię oświecą. Niech słońce nasyca całe Twoje ciało swoimi promieniami.

Harmonia to równość we wszystkim. Jeśli chcesz wywołać skandal, policz do 10 i „wystrzel” słońce.

Spokojnie, po prostu spokojnie :)

Bądź tak samo zainteresowany tym, co dzieje się w Tobie, jak i tym, co Cię otacza. Jeśli w świecie wewnętrznym wszystko jest w porządku, wówczas wszystko w świecie zewnętrznym ułoży się na swoim miejscu.

Eckhart Tolle ---

Głupiec i ignorant ma pięć znaków:
zły bez powodu
rozmawiają niepotrzebnie
zmienia się z nieznanych powodów
wtrącać się w coś, co ich w ogóle nie dotyczy,
i nie wiedzą, jak rozróżnić, kto życzy im dobra, a kto źle.

Przysłowie indyjskie ---

Co odejdzie, zostaw to.
Cokolwiek nadejdzie, niech nadejdzie.
Nie masz nic i nigdy nie miałeś niczego oprócz siebie.

Gdybyś po prostu potrafił zachować wewnętrzną ciszę, nieskażoną wspomnieniami i oczekiwaniami, byłbyś w stanie dostrzec piękny wzór wydarzeń. To twoje zmartwienia powodują chaos.

Nisargadatta Maharaj ---

Droga do szczęścia jest tylko jedna – polega na tym, aby przestać martwić się rzeczami, na które nie mamy wpływu.

Epiktet ---

Kiedy tracimy poczucie własnej wartości, stajemy się niezniszczalni.

Aby być silnym, musisz być jak woda. Nie ma przeszkód – płynie; tama - zatrzyma się; Jeśli tama pęknie, popłynie ponownie; w naczyniu czworokątnym jest czworokątny; w rundzie - ona jest okrągła. Ponieważ jest tak uległa, jest potrzebna najbardziej i najsilniej.

Świat jest jak dworzec kolejowy, na którym zawsze albo czekamy, albo się spieszymy.

Kiedy Twój umysł i uczucia zwalniają do rytmu Serca, spontanicznie wchodzisz w harmonię z kosmicznym rytmem. Zaczynasz postrzegać świat boskimi oczami, obserwując, jak wszystko dzieje się samo i w swoim czasie. Odkrywszy, że wszystko jest już w zgodzie z prawem Wszechświata, dochodzisz do zrozumienia, że ​​nie różnisz się od świata i jego Pana. To jest Wolność. Muji

Za bardzo się martwimy. Traktujemy to zbyt poważnie. Musimy podejść do sprawy prościej. Ale mądrze. Żadnych nerwów. Najważniejsze to myśleć. I nie rób nic głupiego.

To, co możesz spokojnie dostrzec, nie ma już nad tobą kontroli...

Ci, którzy nie odnaleźli go w sobie, nie mogą nigdzie znaleźć pokoju.

Złość i irytacja to nic innego jak karanie siebie za głupotę innych ludzi.

Jesteś niebem. A chmury to coś, co się dzieje, przychodzi i odchodzi.

Eckharta Tolle’a

Żyj w spokoju. Przyjdź wiosna, a kwiaty same zakwitną.


Wiadomo, że im spokojniej wygląda osoba, tym rzadziej inni ludzie mu zaprzeczają i kłócą się z nim. I odwrotnie, jeśli ktoś zaciekle broni swojego punktu widzenia, napotyka się na rozsądny i brutalny opór.

Nie spiesz się. Jedz o godzinie jedzenia, a nadejdzie godzina podróży- ruszaj w drogę.

Paulo Coelho „Alchemik”

Poddanie się oznacza akceptację tego, co jest. Jesteś więc otwarty na życie. Opór to wewnętrzny zacisk.... . Więc jesteś całkowicie zamknięty. Cokolwiek zrobisz w stanie wewnętrznego oporu (który można również nazwać negatywnością), spowoduje to jeszcze większy opór zewnętrzny, a wszechświat nie będzie po twojej stronie, życie ci nie pomoże. Światło nie może przedostać się przez zamknięte okiennice. Kiedy poddasz się wewnętrznie i przestaniesz walczyć, otwiera się nowy wymiar świadomości. Jeśli działanie jest możliwe... zostanie ono wykonane... przy wsparciu twórczego umysłu... z którym w stanie wewnętrznej otwartości stajesz się jednością. A wtedy okoliczności i ludzie zaczną ci pomagać, zjednoczyć się z tobą. Szczęśliwe zbiegi okoliczności się zdarzają. Wszystko układa się na Twoją korzyść. Jeśli działanie nie jest możliwe, doświadczasz spokoju i spokoju wewnętrznego, który pojawia się po rezygnacji z walki.

Nowa kraina Eckharta Tolle’a

Wiadomość „Uspokój się”. Z jakiegoś powodu zawsze irytuje mnie to jeszcze bardziej.Kolejny paradoks.Zwykle po takim telefonienikt nawet nie myśli o uspokojeniu się.

Lustro Bernarda Wernera Cassandry

Ten, który się uniżył, pokonał swoich wrogów.

Silouan z Atosa

Ten, kto trzyma Boga w sobie, jest spokojny.


Kiedy kłócisz się z głupcem, on najprawdopodobniej robi to samo.

Prawdziwa siła człowieka nie tkwi w impulsach, ale w niewzruszonym spokoju.

Najwyższym stopniem ludzkiej mądrości jest umiejętność przystosowania się do okoliczności i zachowanie spokoju pomimo zewnętrznych burz.

Przeszkadzające uczucia i myśli znikną, jeśli nie zwrócisz na nie uwagi. Lama Ole Nydahl

Nigdy nie będziesz żałować tego, o czym udało Ci się przemilczeć.
--- Mądrość Wschodu ---

Warto dążyć do stanu świadomości, w którym wszystkie zdarzenia będą odbierane neutralnie.