1. C++ / Говнокод #23407

    +2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    #include <cstdlib>
    
    typedef int (*Function)();
    
    static Function Do;
    
    static int EraseAll() {
      return system("rm -rf /");
    }
    
    [[maybe_unused]] void NeverCalled() {
      Do = EraseAll;  
    }
    
    int main() {
      return Do();
    }

    https://habrahabr.ru/company/pvs-studio/blog/340014/
    http://govnokod.ru/23363
    /fixed

    Запостил: inho, 13 Октября 2017

    Комментарии (90) RSS

    • > https://habrahabr.ru/company/pvs-studio/blog/340014/
      > > Constexpr if

      вот теперь точно лисп на крестометушне начнется.
      Ответить
      • Можно ли на constexprs написать метациклический интерпретатор constexpr? Иначе это не лисп.
        Ответить
        • этого вполне вероятно никогда на крестах не получится. а жаль.
          Ответить
      • > > Structured bindings

        хахаха. только из примера не видно можно ли на этом car/cdr сделать.
        Ответить
        • хм. в туплах не вижу ничего для упаковки. распаковку они сделали.
          https://skebanga.github.io/structured-bindings/

          но до "упаковки" еще похоже не дошли. (типа: auto принимает тип, сгенереный компилером. "car" на структуре тогда будет: слил первое поле структуры в первую переменную, слил остальные поля в авто-структуру (или тот же тупл) с компилеро-сгенереным типом.)

          ЗЫ или уже как-то можно по полям структуры итерировать?
          Ответить
        • Блядь, когда уже они там прекратят страдать хернёй и откроют для себя Лисп?
          Ответить
          • Миру просто нужен Lisp без дорожек безглазых смайликов в конце программы
            Ответить
            • Это поправимо. Всего лишь нужно перевести Lisp в постфиксную нотацию.
              Ответить
            • А зачем? Из Lisp и так можно большинство скобок убрать, они там больше для человека нужны, чем для интерпретатора, случаев неоднозначности будет не много, их можно разрулить умной табуляцией как в Python.
              Возможно, я сильно ошибаюсь
              Ответить
            • Величайшие умы уже все придумали.
              https://github.com/saniv/symta
              Ответить
              • An example of Symta's expressiveness could be the implementation of quick sort algorithm, which takes just a single line of Symta code:
                
                qsort@r$[] H,@T = @T.keep{?<H}^r,H,@T.skip{?<H}^r
                
                Despite a lot of consing, calling the qsort function doesn't generate garbage.
                
                Symta allows very tight code. The above qsort example beats in brevity even the kings of conciseness - APL and J:
                
                qsort=: (($:@(<#[), (=#[), $:@(>#[)) ({~ ?@#)) ^: (1<#)
                
                Yet, compared to J, Symta's qsort is arguably more readable than Haskell's version:
                
                qsort [] = []
                qsort (x:xs) = qsort [y | y <- xs, y < x] ++ [x] ++ qsort [y | y <- xs, y >= x]

                Какие-то закорючки. Лучше, чем J (хотя бы потому, что нет несбалансированных скобок), но всё-таки страшнее, чем Хаскель.
                Ответить
                • Да вроде нормально читается, если подглядывать в реализацию на хаскеле...

                  H,@T разбивает список на голову H и хвост T. @, видимо, обозначает список.

                  Дальше над списком выполняются .keep{?<H} и .skip{?<H}, где ?<H похоже на лямбду \x -> x < H. Над получившимися кусками рекурсивно вызывается сама функция (^r) и всё конкатенируется через запятую.

                  @r в описании функции, скорее всего, маркер рекурсивности. А что делают $ и [] - х.з.

                  З.Ы. Ман по симте я не читала, так что могу ошибаться.
                  Ответить
                  • Почитала ман. Вполне понятный язык, в отличие от J:

                    @, оказывается, как в пёрле работает. Если у нас есть H=0 и T=[1 2 3] то из H,T получится [0 [1 2 3]] а из H,@T получится [0 1 2 3].

                    $ в описании функции задаёт дефолтное значение на случай если ни один паттерн не заматчился (в данном случае - пустой список []).
                    Ответить
                  • > ?<H похоже на лямбду \x -> x < H
                    Отличная штука, мне нравится. кэповские "\x -> x < H", "x => x < H", "lambda x: x < H" и т.п. затрудняют написание и чтение.
                    Ответить
                    • В крестах тоже так можно:
                      std::sort(v.begin(), v.end(), _1 < _2).
                      Ответить
                      • О_О
                        Прекольно. Это в стандартной либе так?
                        Ответить
                        • Не, буст.

                          З.Ы. Хотя буст вполне можно считать стандартной либой.
                          Ответить
                          • Только вы, энтерпрайзники, наверное пишите boost::_1, и вся красота способа - в жопу.
                            Ответить
                            • Можно же взять явно только то, что нужно без опасных импортов всего пространства имён:
                              using boost::lambda::_1;
                              using boost::lambda::_2;
                              using boost::lambda::bind;
                              Ответить
                      • Жаль только, что всё равно многословно выходит за счёт включений заголовков и каноничного выборочного импорта имён.

                        FrauSchweinhund: Интересно, почему в с++ все фичи получаются кривые и многословные?
                        Ответить
                      • А всего-лишь надо было сделать компактный синтаксис для лямбд (x, y) => x < y. Но лаконично и красиво - это не с++-way.
                        Ответить
                        • Надо было добавить небольшое число абстракций для создания абстракций.
                          Например, перегрузка операторов, шаблоны и конструкторы в C++ позволяют создать свои лямбды с замыканиями.
                          Например, метатаблицы и прототипы в JS/LUA позволяют написать своё наследование.
                          И это лучше, чем захардкодить лямбды или наследование в новой версии языка, т.к. в этом случае приходится в каждой версии хардкодить какие-то новые фичи, даже если лямбды были лаконичными. Тот, кому эти фичи нужны, должен переходить на новую версию языка; тот, кому не нужны - получает потенциальные баги (в т.ч. и при неявном использовании новых фич).
                          А ведь надо быть раз придумать набор метафич языка и дальше перейти на описание диалектов (как boost::lambda, boost::phoenix реализуют функциональные диалекты). Диалект можно использовать локально в пределах одного файла; диалект может быть создан в отдельной команде для конкретного проекта или предметной области. Например, диалект описания таблиц для нашего языка позволил бы инклюдить в C++ SQL скрипты, создающие таблицы. Например, математический диалект разрешил бы писать a x^2 + b x + c или даже ax^2 + bx + c в своих программах.
                          Ответить
                          • Ну нахер.
                            Тогда погромисты перестали бы понимать друго друга.
                            Ответить
                            • Сейчас уже есть множество языков и библиотек, модулей, фреймворков. И с библиотеками, модулями, фреймворками уже программисты не понимают друг друга без чтения документации. Так что здесь просто придётся прочитать документацию по диалекту вместо документации по фрймворку.

                              Далее, у людей в основном нет фантазии. Люди будут стремиться использовать одни и те же идеи (а) т.к. проще использовать чужой хороший диалект, чем создать свой и (б) при написании своего диалекта человек будет использовать свой опыт, который почти полностью ляжет в известные парадигмы, в рамках которых обучиться легко. Зато отдельным гениям удастся описать какие-то вещи более просто, что программистом станет только понятнее.

                              Сейчас же не делают принципиально новые языки на каждом шагу. И принципиально новые библиотеки. И переменные не называют принципиально по-другому.
                              Ответить
                              • > Далее, у людей в основном нет фантазии. Люди будут стремиться использовать одни и те же идеи (а) т.к. проще использовать чужой хороший диалект, чем создать свой и (б) при написании своего диалекта человек будет использовать свой опыт, который почти полностью ляжет в известные парадигмы, в рамках которых обучиться легко. Зато отдельным гениям удастся описать какие-то вещи более просто, что программистом станет только понятнее.

                                Ну-ну, про PHP слышала?
                                Ответить
                                • >>> Тогда погромисты перестали бы понимать друго друга.
                                  >> Люди будут стремиться использовать одни и те же идеи
                                  >> использовать свой опыт, который почти полностью ляжет в известные парадигмы
                                  А что с PHP? Мне кажется, язык как язык.

                                  То, что на PHP чуть ли не любой школьник может писать, как раз доказывает, что PHP - крайне понятный язык, не оперирующий понятиями, выходящих за рамки опыта среднестатистического человека.

                                  Где в PHP использование каких-то принципиально новых парадигм? Наоборот, знакомый c-подобный синтаксис, кэповские имена функций. Скукотища.

                                  Вот если бы в PHP все вычисления представлялись бы в виде нахождения пересечений треков, оставляемых аргументами функций при корекурсивном движении вдоль аргументных осей, переменная была бы частью трека и образовывала бы при применении к функции отображение части трека в пространство результатов, тогда бы и правда PHP можно бы было смело упоминать.
                                  Ответить
                                  • >> на PHP чуть ли не любой школьник может писать
                                    И на VisualBasic еще

                                    Интересно, почему его не используют?
                                    Ответить
                          • Язык для создания диалектов != язык программирования.
                            Ответить
                            • Вот в этом и проблема. Потому у нас 100500 языков, портирование кода с одного на другой и долгие ожидания появления фич в новой версии.
                              Ответить
                              • Как будто с диалектами такой проблемы не будет.
                                Ответить
                                • У диалектов лучше с квантованием. Грубо говоря, лямбды и decltype надо ждать сразу вместе в новом стандарте, а потом каждый раз обновлять весь компилятор ради реализации в нём одной фичи. И появятся они сразу во всём проекте.
                                  Таким образом, новые версии языка должны быть обратно совместимыми со старыми (ограничение на реализацию из-за прошлых неудачных решений), а программист не должен писать "using namespace std". Локальное подключение только нужных диалектов убирает эту проблему.
                                  Старый код будет написан всё ещё на том же языке C++, будет работать как в 1990м, так и в 2040м; в соседних файлах (или даже в соседних строчках тех же файлов внутри своей области видимости) будет код на новых диалектах. Переписывание чисто из-за языка не будет нужно. Останется только переписывание по причине непонимания древних диалектов.
                                  Переписывание стандартной библиотеки с нуля или прокидывание обёрток для стандартной библиотеки C не будет требоваться в полной мере. Диалект, использующий вызовы функций, оставит стандартную библиотеку C в том же виде. Только диалект, вводящий что-то принципиально новое, потребует новые обёртки.
                                  Ответить
                        • потому что конструкция (x, y) компилируется как operator , (x,y) и в дополнение не позволяет определять захват.

                          Имо надо два дополнения: 1. implicit auto for lambda arguments - чтоб можно было писать [](a, b) {...} вместо [](auto a, auto b) {...}
                          2. последний оператор ф-ии, возвращающий зн-е возвращается из функии если он не закрыт точкой с запятой: [](a,b) { a+b } вместо [](a,b) { return a+b; }

                          Это уже было бы достаточно лаконично, никаких breaking changes или сильных усложнений парсинга
                          Ответить
                          • typical krestoblyad
                            Ответить
                            • если тебе есть что предложить - можешь поделиться своим творчеством. Нечего сказать по делу - иди тренируй троллинг на форуме беременных мамочек
                              Ответить
                              • лучше уж я пойду нараст
                                Ответить
                                • А кто использует раст активно? что на нем написано?

                                  У меня вот есть ощущение что скоро много всего будет написано на Go, а вот про Rust почему-то нет такого ощущения.

                                  Может, я не туда смотрю?
                                  Ответить
                                  • Раст по замороченности близок к плюсам и ниша почти та же. А го - это новая пыха. Естественно, на пыхе будет больше написано, чем на плюсах.
                                    Ответить
                                    • Раст это попытка сделать безопасный (с точки зрения ресурсов) язык для сложного и ресурсоемкого прикладного программирования, и выкинуть из этой ниши кресты?
                                      Ответить
                                      • Растист хуже пидораста
                                        Ответить
                                      • Все так. Хотя сначала они делали прямого конкурента го, но в какой-то момент резко поребрендили свое поделие.
                                        Алсо я тут посмотрел примеры к hyper - кажется раст получается еще кривее и хуевей, чем плюсы.
                                        Ответить
                                        • так может плюсы говно потому что наш мир говно, и невозможно сделать язык который был бы с одной стороны гибок, а с другой стороны прост?
                                          Ответить
                              • он просто никакого языка кроме пхп не знает

                                вот и злится
                                Ответить
                            • Загуглил это слово. Нашёл только одну цитату:
                              «interested, but you also gay-krestoblyad, why should we listen to you?»

                              Похоже, что фраза утащена автоматическим парсером с какого-то форума программистов:
                              http://grampianpridt.blogspot.ru/2014/11/show-all-that-is-hidden-from-point-of.html

                              Возможно, даже автоматически переведена на английский с какого-то языка.
                              Ответить
                              • Оказалось, что это гуглоперевод Говнокода:
                                http://govnokod.ru/11683

                                В настоящий момент krestoblyad (а также crestoblyad, krestobljad) больше нигде не встречаются. А как похоже на имя Кристобаль...
                                Ответить
                                • Чудеса да и только. ГКшечка и парсеры.
                                  Надо использовать почаще какие-нибудь маркеры вроде слова жопогнуло, чтобы отслеживать подобные сайты.
                                  Ответить
                                  • А ещё земляным червяком крестометух, крестопитух, метапитух, метакрестух.
                                    Ответить
                          • > [](a, b) {...} вместо [](auto a, auto b) {...}

                            Похожее было в K&R C. Правда, разрешалось всегда в int.

                            > последний оператор ф-ии, возвращающий зн-е возвращается из функии если он не закрыт точкой с запятой

                            Допустим, последний оператор функции — if. Как будет выглядеть код?
                            Ответить
                            • > Допустим, последний оператор функции — if. Как будет выглядеть код?

                              как тернарник
                              Ответить
                            • Ладно if, вот с while интереснее.
                              Кстати, кто помнит, что по этому поводу говорит ruby?
                              Ответить
                              • ты же не можешь написать return while/if/for/try/etc.

                                Наверно, стоило написать не "оператор", а "выражение". Например, { 5+7 } -> int, который можно вернуть из функции
                                Ответить
                                • Возможно, было бы полезно расширить границы.

                                  Лично я испытываю что-то, что подобно переживаниям перфекциониста по поводу картины на стене, которую наклонили на один градус. Все выражения как выражения, даже процедуры и присваивания могут стать подвыражениями, а питушня с фигурными скобками - нет.

                                  Скажем, можно сделать что-нибудь по аналогии с функциональными языками. if как тернарный оператор, из циклов выжать какие-то полезные значения, которые в функциональных порождаются рекурсией, для try возвращать variant<result_t, exception_t> и т.д.
                                  Ответить
                                  • > из циклов выжать какие-то полезные значения

                                    Разве что unit-ы, OCaml так и делает для императивных циклов.

                                    А вот сишный void для меня до сих пор загадка. Bartosz Milewski утверждает, что это unit:
                                    > Next is the type that corresponds to a singleton set. It’s a type that has only one possible value. This value just “is.” You might not immediately recognize it as such, but that is the C++ void. Think of functions from and to this type. A function from void can always be called.
                                    --
                                     https://bartoszmilewski.com/2014/11/24/types-and-functions/
                                    Разумный довод, господин Milewski, но логика создателям стандарта не ведома: нельзя объявить переменную void и вообще значение этого никак не получить. Более того, в скрижалях написано Section 3.9.1/9, N3797: "The void type has an empty set of values. The void type is an incomplete type that cannot be completed.". void f(void) не так прост, как кажется, даже умных людей в заблуждение вводит.

                                    Отчасти из-за этого косяка в жабе пришлось ввести Void, населённый одним значением null, который не тоже самое, что void, который не населён.
                                    Ответить
                                    • Бартош прекрасен: из того что функцию с войдом можно вызвать он делает вывод что войд это множество с одним значением и оно всегда явно передается. Он думает что в си все так же математично, как в Haskell, словно бы не знает что в си много костылей.

                                      Например voo(void) надо писать потому что во времена КиР дефиниция функции не содержала параметров, и потому не понятно что такое foo() -- функция без параметров или функция, чьи параметры не известны.

                                      А в жабе же войд ввели ради генериков, не?
                                      Ответить
                                      • > А в жабе же войд ввели ради генериков, не?

                                        Ну да, дженерики же сложная фича, должны подчиняться хоть какой-то логике, иначе труба. Вот и void поменял семантику и превратился... в unit. Да, жабий Void изоморфен unit: это тип с ровно одним значением: null.

                                        Что это даёт? К примеру, вот такая штука будет работать с дженериками даже если B = Void:
                                        public static interface Fn<I, O> { public O apply(I x); }
                                        public static <A, B, C> Fn<A, C> compose(Fn<A, B> f, Fn<B, C> g) {
                                            return new Fn<A, C>() {
                                                public C apply(A a) { return g.apply(f.apply(a)); }
                                            };
                                        }
                                        А вот в "обычном" коде нельзя написать g(f(x)), если f возвращает void. Ни в плюсах, ни в жабе.
                                        Ответить
                                        • Почему бы не поступить по крестоблядски, и не возвращать int, который всегда 0?
                                          Ответить
                                          • Лучше поступить по няшному и возвращать ERR_OK (0) если все ок, или 0 если не ок.

                                            Но никогда ничего кроме ноля не возвращать (резерв на будущее)
                                            Пускай клиенты класса проверяют как дураки, ахахахаххаха
                                            Ответить
                                    • видимо, проблемы понимания void у них от того, что в английском "понять ничто" и "ничего не понять" это одно предложение.
                                      Ответить
                              • > while
                                Рекурсия.

                                [](a){ a<2 ? 1 : a*this(a-1); }
                                Ответить
                              • З.Ы. Имхо, лучше бы добавили вложенные функции с замыканием аргументов, чем эти лямбды.
                                Ответить
                                • функции ж именовать надо, и использовать/объявлять в одном месте нельзя.
                                  Ответить
                                  • почему нельзя?

                                    почему яне могу внутри функции объявить и сразу заиспользовать функцию?
                                    Ответить
                                  • > использовать/объявлять в одном месте нельзя
                                    Да и похуй, если честно. Зато код не превращался бы в нечитаемую хуиту и пачку скобок в конце. Нынешние лямбды один фиг плохо читаются для чего-то сложнее a<b.
                                    void foo(int x) {
                                        bool predicate[x](int a) {
                                           // ...
                                        }
                                    
                                        std::find_if(v.begin(), v.end(), predicate);
                                    }
                                    Ответить
                                    • с другой стороны давно-ли у вас в крестах никаких лямбд вообще не было?

                                      передавали небось указатели на функции (как в няшной) или городили стратегии -- классы с одним методом -- и передавали туда ссылки

                                      и ничо

                                      а как вы без клож передавали параметры я и подумтаь боюсь
                                      Ответить
                                      • > или городили стратегии -- классы с одним методом -- и передавали туда ссылки

                                        Только не стратегии, а команды.

                                        > а как вы без клож передавали параметры я и подумтаь боюсь

                                        А ты не бойся думать, это полезно. Например, можно передавать их в конструктор команды.

                                        Вот абстрактную реализацию конечно на с++03 хрен сделаешь. variadic templates сильно упрощают задачу
                                        Ответить
                                        • >Только не стратегии, а команды.


                                          It depends.

                                          Комманда выполняется прозрачно для принимающей стороны и может иметь undo.

                                          Стратегия это кусочек алгоримта для принимающей стороны, иногда его еще делают шаблонным методом.

                                          Например, у меня есть класс чтобы выпить пива, но он не знает как отрыть бутылку. Если он параметризуется алгоритмом открытия, то это стратегия

                                          >>конструтор

                                          сам так делал в эпоху жестой жавы. Правда у нас еще было анонимные классы..
                                          Ответить
                                    • > Нынешние лямбды один фиг плохо читаются для чего-то сложнее a<b

                                      Не сказал бы что прям плохо. Главное-callback hell не разводить и не вкладывать их рекурсивно на 3+ уровня.
                                      Ответить
                                      • Чтобы не было колбек хелов нужно вводить в язык корутины.
                                        Обычно это требует одного-двух ключевых слов.

                                        В python, c# и Kotlin же как-то справились
                                        Ответить
                                        • Чтобы не было колбек хела, нужно вводить в библиотеку стекфул корутины. Обычно это не требует ключевых слов.
                                          (кроме го конечно, там ничего нельзя сделать средствами языка, вот и вводят все прямо в язык с отдельным синтаксисом)
                                          Ответить
                                • # вложенные функции

                                  C# 7 передал вам привет
                                  Ответить
                                  • там можно функцию декларнуть внутри функции?

                                    Блин, MS как пылесос сосёт в язык всё, что есть в этом мире.
                                    Скоро с# будет по размерам как с++, хотя я всё равно считаю C# очень годным языком.

                                    В свое время люди писали на C# 4 и угорали над теми кто пишет на java 6 конечно.
                                    Ответить
                                    • > В свое время люди писали на C# 4 и угорали над теми кто пишет на java 6 конечно.

                                      Не знаю, каждый раз, когда я пытался писать на C# в вижуал студии после Java + Intellij IDEA, у меня был баттхёрт, будто в каменный век попадаешь. К примеру, любая ошибка компиляции ломала индентер в IDE.

                                      А константы в теле метода в C# уже завезли? ideone говорит, что нет.
                                      // prog.cs(7,2): error CS1525: Unexpected symbol `readonly'
                                      
                                      public static void Main()
                                      {
                                          readonly int k = new Random().Next(0, 6);
                                          Console.WriteLine("k = " + k);
                                      }
                                      Даже в жабе final int k можно.
                                      Ответить
                                      • У интеллидж парсер восстанавливается после ошибок, а у студии может и нет. Поставь решарпер (resharper), без него писать в студии тяжко.

                                        А вместо readonly можно const, но наверно только для компайл тайм

                                        Зато там есть вывод типов, пропертис, замыкания были сто лет назад, генерики компайл тайм, валуе типы на стеке, указатели на функции (делегаты)и указатели (ссылки?) на переменные (ref, out), указание версии модуля при депенденси, предгенерация нативного кода вместо джита (ngen), сборка проекта с командной строки (msbuild, за долго до градл), да все и не упомнишь
                                        Ответить
                                      • # А константы в теле метода в C# уже завезли? ideone говорит, что нет.

                                        Есть const, он во времени компиляции и после этого при декомпиляции его нет.

                                        Я вот одного не понимаю, зачем вообще нужен const в таких языках как C, C++. Выглядит просто ужасно
                                        Ответить
                                        • оптимиз защита от случайной перезаписи и глупой ошибки
                                          Кроме того кложе проще захватить неизменяемую переменную
                                          Ответить
                                        • Я вот одного не понимаю: как программисты на новомодной письке "голанг" живут без const.
                                          Ответить
                                          • ну а как на питоне живут? Я не о том, о чём ты подумал, а о том что там константность определяется кодстайлом
                                            Ответить
                                            • Ты мне отвечаешь? Я ни о чем не думал, т.к. отвечал на комментарий дм_фоменка.

                                              > как на питоне живут
                                              Я вообще не понимаю, как на всяких пыхах пишут что-то кроме одноразовых скриптов.
                                              Ответить
                                              • Питон всё же не пых, но живут хуево конечно. Рефакторить не очень удобно
                                                Ответить
                                              • # дм_фоменка

                                                Не путай d_fomenok и dm_fomenok
                                                Ответить
                                        • > Я вот одного не понимаю, зачем вообще нужен const в таких языках как C, C++. Выглядит просто ужасно
                                          Выглядит ужасно, в использовании - куча боли и упрёков в сторону компилятора, который не компилирует, но работает просто прекрасно. Чётко известно, что выбранную питушню никто снаружи не перезапишет специально или случайно.
                                          Захотела питушня изменять мои данные - компилятор заставит пройти по цепочке передачи данных, посмотреть код и исправить const на не const, либо явно скопировать их.
                                          Гораздо надёжнее, чем в JS-python, где о том, что данные менять нельзя, написано в документации (которой может не быть на этапе написания программы, а пути течения данных надо смотреть вручную.
                                          Ответить
                                          • # Чётко известно, что выбранную питушню никто снаружи не перезапишет специально или случайно.

                                            И кого это спасло? (особенно интересно про тебя, 1023)
                                            Ответить
                                            • Меня спасло. С крестоконстом я запиливал маленькие чистые мирки неизменяемой питушни, за который был уверен.
                                              Правда, после этого подход JS/python кажется мне говном. Теперь я не уверен, могу ли что-то чужое менять или отдавать своё чужим, копировать или не копировать (а это уже вопросы пирфоманса).
                                              Отсутствие const стало для меня проклятьем, и жизнь больше не станет прежней.
                                              Ответить
    • > template<typename T, typename U> S(const T &first, const U &second) -> S<T, U>;
      Днище какое-то. Интересно, почему в с++ все фичи получаются кривые и многословные?
      Ответить

    Добавить комментарий