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

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    template<typename T>
    class IsClassT {
      private:
        typedef char One;
        typedef struct { char a[2]; } Two;
        template<typename C> static One test(int C::*);
        // Will be chosen if T is anything except a class.
        template<typename C> static Two test(...);
      public:
        enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
        enum { No = !Yes };
    };

    Как эта поебота работает?
    Что такое "int C::*"?

    Запостил: A3APTHblu_nemyx, 19 Марта 2019

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

    • #include <iostream>
      using namespace std;
      
      template<class T>
      struct IsChar {
          static bool value;
      
          static char foo(char c) {return true;}
      
          static int foo(...) {return false;}
      
          template<class C>
          static bool bar() {
              return foo(C());
          }
      };
      
      template<class T>
      bool IsChar<T>::value = IsChar<T>::bar<T>();
      
      struct Hui {
      };
      
      int main() {
          cout << IsChar<char>::value << endl;
          cout << IsChar<int>::value << endl;
          cout << IsChar<Hui>::value << endl;
      }


      какого хуя?
      Ответить
      • Именно поэтому я за «PHP».
        Ответить
      • SFINAE не срабатывает при C == int потому что int можно передать в foo(char).
        Ответить
        • Меня больше бесит, что uint8_t выводится в стрим как символ, а не как число.
          Ответить
          • Комитет тебя услышал и ввёл тип std::byte!

            …его, правда, в стрим вообще выводить нельзя.
            Ответить
      • Именно поэтому я за "Си":
        #include <stdio.h>
        
        #define CAT_(x, ...) x ## __VA_ARGS__
        #define CAT(...) CAT(__VA_ARGS__)
        
        #define CHECK_N(x, n, ...) n
        #define CHECK(...) CHECK_N(__VA_ARGS__, 0)
        #define PROBE(x) x, 1
        
        #define IS_CHAR(t) CHECK(CAT_(IS_CHAR_, t))
        #define IS_CHAR_char PROBE(~),
        
        #define QUOTE_(...) #__VA_ARGS__
        #define QUOTE(...) QUOTE_(__VA_ARGS__)
        
        #define PRINT(...) puts(QUOTE(__VA_ARGS__))
        
        int main(void)
        {
            PRINT(IS_CHAR(char), IS_CHAR(int), IS_CHAR(char**));
            return 0;
        }
        https://ideone.com/B4EWWS
        Ответить
        • Не знаю, как сделать, чтобы char** и т.п. возвращали 0 :(
          Ответить
          • Я зделяль:
            #include <stdio.h>
            
            #define CAT_(x, ...) x ## __VA_ARGS__
            #define CAT(...) CAT(__VA_ARGS__)
            
            #define CHECK_N(x, n, ...) n
            #define CHECK(...) CHECK_N(__VA_ARGS__, 0)
            #define PROBE(x) x, 1
            
            #define IS_CHAR(t) CHECK(CAT_(IS_CHAR_, t(~,1)))
            #define IS_CHAR_char(...) __VA_ARGS__
            
            #define QUOTE_(...) #__VA_ARGS__
            #define QUOTE(...) QUOTE_(__VA_ARGS__)
            
            #define PRINT(...) puts(QUOTE_(__VA_ARGS__))
            
            int main(void)
            {
                PRINT(IS_CHAR(char), IS_CHAR(int), IS_CHAR(char**), IS_CHAR(char(*)()));
                return 0;
            }
            https://ideone.com/ZHLHCI
            Ответить
            • Блин, с "typeof" не работает :(
              Ответить
              • Нужен тайпоф выполняющийся при или перед препроцесснигом.
                Ответить
                • Пре-препроцессинг!
                  Ответить
                  • Слишком нерасширяемо.
                    Нужно ввести новый синтаксис для задания точного порядка, в котором будут препроцессированы токены:
                    #define CAT(x, y) x#[-1] ## y#[-1]
                    #define STR(x) #x#[42]

                    Здесь препроцессор сделает три прохода: на первом будут препроцессированы токены с приоритетом -1, на втором — с нулевым приоритетом и, наконец, на последнем проходе будет обработан 42-й приоритет.
                    Таким образом CAT объединит уже препроцессированные x и y без необходимости введения дополнительных макросов, а STR будет возвращать правильное строковое представление x:
                    STR(CAT(Kakoy, Bagor));  // == "KakoyBagor"
                    Ответить
                    • Ничего не понял, но я за «M4».
                      Ответить
                      • А Я ЗА АК-74.
                        Ответить
                        • А Я ЗА РПК-74.
                          Ответить
                          • А Я ЗА "1974", ОН ПОДАРИЛ НАМ "РАМОНОВ".
                            Ответить
                            • 'Сосла́н Лю́двикович Рамо́нов (кударск.- Рæмонты Людвичы фырт Сослан)

                              ты про него?
                              Ответить
                              • Это что за покемон?

                                P.S. Нагуглил. Если борец, то он в 1991-м только родился.
                                Ответить
                                • Ну тебя что, в гугле забанили?

                                  Это друг нашего Стертора из соседнего государства.

                                  Цхинвал,Республика Южная Осетия — российский борец вольного стиля осетинского происхождения, чемпион Олимпийских игр 2016 в весе до 65 кг, чемпион и призёр чемпионатов России и мира, обладатель Кубков европейских наций, призёр Кубков мира. Капитан Вооружённых Сил Российской Федерации.

                                  Победитель всероссийского турнира на призы Сослана Андиева (2007);

                                  Мало кто знает, но многих осетинов зовут Сослан.
                                  Например, Стертора
                                  Ответить
                              • Кудар небось тоже? Говно.
                                Ответить
                              • "Рамоны". Это группа такая. Может ты слышал их песни: "Съешь эту крысу", "Я хочу понюхать клей", "Мне похуй", "Иди психический", "Ноль ноль НЛО", "Я хочу быть седативным", "Волосы собаки"?
                                Ответить
                    • НИКОГДА НЕ ПОНИМАЛ, ПРИ ЧЁМ ЗДЕСЬ КОТ?
                      Ответить
                      • Котенация строк.
                        Ответить
                        • Борманд, ты работал со сканнерами по усб?
                          Я верно понимаю что там просто device class специальный поверх которого работает драйвер, а все эти WIA, SANE, и TWAIN это просто програмные интерфейсы?
                          Ответить
                          • Там вроде даже не класс, а лютая проприетарщина между каждой железкой и её драйвером.

                            По крайней мере, у моего сканера даже прошивки не было, её заливал драйвер с компа. Для линукса приходилось выковыривать эту прошивку из виндового пакета с дровами.

                            Интерфейсы чисто программные, да.
                            Ответить
                            • Оказывается, у сенсорных панелей ноутбуков бывает такая же фигня: в девайсе прошивки нет, её заливает драйвер с компа.
                              Ответить
                              • Заливал "прошивку" с cp866 в девайс "видеокарта" посредством драйвера "keyrus" когда это еще не было мейнстримом, проверь
                                Ответить
                                • Ты заливал «прошивку» в «теневой» блок памяти, в который был скопирован видеобиос.
                                  Ответить
                            • Но класс-то есть, что же он делает?
                              или он как printer class, то-есть говорит просто "вот порт сканнера" а что туда писать -- это уже проблема драйвера?
                              Ответить
                          • А ВОТ ТЕПЕРЬ Я РЕАЛЬНО НЕ ПОНИМАЮ, ПРИ ЧЁМ ЗДЕСЬ КОТ.
                            Ответить
                    • typeof ВЫПОЛНЯЕТСЯ ПРИ КОНПЕЛЯЦИИ, А НЕ ПРИ ПРЕПРОЦЕССИНГЕ, ПРИОРИТЕТЫ НЕ ПОМОГУТ.
                      Ответить
                      • ЗНАЧИТ, НАМ НУЖЕН ПРЕПРОЦЕССОР, КОКОКОКОТОРЫЙ УМЕЕТ ВЫЧИСЛЯТЬ КОКОКОКОНСТЭКСПРЫ.
                        Ответить
                        • Не помню кто и где, но было предложение использовать PHP в качестве препроцессора ;)
                          Ответить
                          • Есть такое:
                            http://govnokod.ru/24379
                            и ещё где то было в комментах в нескольких тредах.
                            Ответить
                          • Да, PHP или любой другой навороченный скриптовый язык в качестве препроцессора –— это круто, но нам хотелось бы вычислять typeof, а для реализации typeof придётся изобретать полноценный парсер C++.
                            Ответить
                          • Так PHP и есть PHP Hypertext Precprocessor.

                            некоторые сумасшедшие пытаются использовать его как язык программирования. Получается плохо
                            Ответить
                            • Некоторые шумашешие ещё придумавыют шаблонизаторы для "PHP".
                              Ответить
                              • почему нет нормального шаблонизатора для языка шаблонов в C++?
                                Ответить
        • template <typename>
          struct is_char : std::false_type {};
          
          template <>
          struct is_char<char> : std::true_type {};
          
          int main() {
            static_assert(is_char<char>() && !is_char<int>() && !is_char<char**>() && !is_char<char(*)()>());
          }


          https://wandbox.org/permlink/xKirxHNm6Rbx8ePR
          Ответить
          • #include <type_traits>
            
            template<typename T>
            constexpr bool is_char = std::is_same_v<T, char>;
            
            int main() {
              static_assert(is_char<char> && !is_char<int> && !is_char<char**> && !is_char<char(*)()>);
            }


            https://wandbox.org/permlink/g46U2AeBTyx6Qcqy
            Ответить
            • Оно то да. Мое было в качестве иллюстрации. Просто лень за пятку укусила писать constexpr static bool value = true/false, потому заюзал boilerplate из std::integral_constant
              Ответить
            • ИДИТЕ НАХУЙ СО СВОИМИ ШОЬЛОНАМИ! Я ЗА МОКРОСЫ!
              Ответить
              • СОЗДАЙ СВОЙ ТРЕД ПРО МОКРОСЫ И ТЕКИ ТАМ
                А ЗДЕСЬ ТЕКУТ ПО "SFINAE"
                Ответить
          • Это я уже понял. Как сделать со "SFINAE"?
            Ответить
            • Зачем тебе тут SFINAE? Ты хочешь его понять на таком примере?

              Я тебе вот чтоб скажу: чтоб понять SFINAE, надо сначала понять SFINAE. Substitution failure is not an error. Т.е. если подставить в шаблон некие параметры а в результате выходит поеботня, шаблон игнорируется, а не выдается ошибка компиляции.

              Другими словами, SFINAE нужен чтоб в некоторых ситуациях игнорировать один шаблон (специально создавая невалидный код) чтоб использовать другой в некоторых ситуациях.
              Ответить
            • Как то так, крч.
              template <typename>
              struct sfinae {};
              
              template <>
              struct sfinae<char> { using type = std::true_type; };
              
              template <typename T>
              struct is_char {
              private:
                template <typename U>
                constexpr static typename sfinae<U>::type check(U*);
                template <typename U>
                constexpr static std::false_type check(...);
              public:
                constexpr static bool value = decltype(check<T>(nullptr)){};
                constexpr operator bool() const { return value; }
              };
              
              int main() {
                static_assert(is_char<char>() && !is_char<int>() && !is_char<char**>() && !is_char<char(*)()>());
              }


              https://wandbox.org/permlink/kQhjVGRHQZRYVbjD

              Поэтому я за "обдуманный выбор средств решения задачи".
              Ответить
            • Вот хороший пример работы SFINAE:
              #include <iostream>
              #include <iomanip>
              #include <vector>
              
              template<typename T>
              auto my_begin(T & t) -> decltype(t.begin())
              {
                  return t.begin();
              }
              
              int main()
              {
                  std::vector<int> a{};
              
                  auto x = my_begin(a);
                  std::cout << std::boolalpha << (x == a.begin()) << std::endl;
              
                  int b = 1;
                  auto y = my_begin(b);
              
                  return 0;
              }

              https://wandbox.org/permlink/Sv1dM02fs4ijHRQn

              Конпелятор ругается не на то, что у переменной b нет метода begin, а на то, что подходящая перегрузка не найдена:
              prog.cc:19:24: error: no matching function for call to 'my_begin(int&)'


              И дальше он поясняет за SFINAE:
              prog.cc:6:6: note:   template argument deduction/substitution failed:
              prog.cc: In substitution of 'template<class T> decltype (t.begin()) my_begin(T&) [with T = int]':
              prog.cc:19:24:   required from here
              prog.cc:6:36: error: request for member 'begin' in 't', which is of non-class type 'int'
                  6 | auto my_begin(T & t) -> decltype(t.begin())
                    |                                  ~~^~~~~

              То есть при поиске перегрузки шаблон был проигнорирован, потому что при подстановке int в качестве T происходит ошибка.
              Ответить
              • А «clang» ещё понятнее поясняет:
                prog.cc:19:14: error: no matching function for call to 'my_begin'
                    auto y = my_begin(b);
                             ^~~~~~~~
                prog.cc:6:6: note: candidate template ignored: substitution failure [with T = int]: member reference base type 'int' is not a structure or union
                auto my_begin(T & t) -> decltype(t.begin())
                     ^                            ~
                Ответить
                • Не люблю шланг, он часто обламывает мои мокроёбства.
                  Ответить
                  • я пишу под llvm на свифте и теку на яблоко без всяких мокроёбств
                    Ответить
                    • Складывается впечатление, что ты постоянно течёшь.
                      Ответить
                      • В контексте языков без сборки мусора, течь -- не очень-то и хорошо, а если точнее -- очень плохо.
                        Ответить
                        • Для языков со сборкой мусора - ещё хуже.
                          Ответить
                        • Именно поэтому я за "PHP".
                          Ответить
                        • У свифта кажется что рефкаунтинг, так что утечь там можно только посредством референс сайкла.

                          Простое проебываение ссылки типа создать питушка в куче и тутже проебать на него указатель там не канает (копулятор уменьшит счетчик ссылок на питушка и ёбнет его)

                          А вот так можно и утечь:
                          Питух ссылается на курочку
                          Курочка на питуха
                          Обе ссылки жестские и потому они никогда не осовбодятся (нежетские ссылки не считаются и при смерти питушка превратятся в nil)

                          У ГЦ такой проблемы нет (остров изоляции), но и там тоже бывает течка, хотя и с другой немного семантикой

                          При той течке ссылка не проябывается, но некий код приводит к постоянному увеличению дерьма в куче
                          Ответить
                          • Щито?
                            Свифт течёт, или я не правильно тебя понял? В удаление циклических ссылок сейчас каждый говноязык умеет, даже "PHP".
                            Ответить
                            • Циклы нужно разрывать руками.
                              Так было в Objective C, так же осталось и в Swift.

                              https://cocoacasts.com/what-are-strong-reference-cycles

                              Ничего страшного нет, надо просто иногда включать мозг.
                              Строго говоря даже для языков с ГЦ не плохо бы понимать что там у тебя в куче делается
                              Ответить
                              • Какой багор )))
                                Поэтому я за "PHP".
                                Ответить
                                • зато у свифтеров есть прикольный профулятор instruments на основе dtrace
                                  http://www.xmcgraw.com/wp-content/uploads/2015/01/image-time.jpg


                                  а у пыхеров есть только сраный xhprof
                                  Ответить
                                • а я за няшную

                                  там приходится оче много думать про управление памятью.
                                  Если один раз расслабишься то всё, пиздец

                                  Потому там такие штуки на подкорке и таких проблем нет
                                  Ответить
                                  • А я за TINY MODE реального режима

                                    там физически нельзя потечь памятью, шах и мат
                                    Ответить
                                    • Никто не мешает COM-файлу выделять память через диспетчер памяти операционной системы и оперировать с этими блоками через длинные указатели.

                                      Можно захавать всю оперативку, доступную досовским программам, а потом вызвать функцию «Terminate & stay resident» и остаться в памяти.
                                      Ответить
                                      • подскажи пожалуйста через какое прерывание я могу выделить память в MS-DOS.

                                        Учти только что речь про DOS 1.0 и 8086, так что никаких этих ваших EMS и XMS
                                        Ответить
                                        • Через INT 21H. Или тебя функция интересует? Гугли MCB —– «memory control block».

                                          P.S. Функция 48H –— выделить блок (BX=кокококоличество параграфов); 49H –— освободить блок (ES=сегментная часть адреса блока).
                                          Ответить
                                          • вероятно ты про
                                            Function 48h - Allocate memory


                                            Но память и так моя, зачем мне это? чтобы саомму себя ограничивать?
                                            Ответить
                                            • Эта функция выделяет память, которая за пределами запущенной программы.

                                              Это нужно, например, чтобы при запуске программы из программы (например, system("pause");) дочерней программе этот блок не был доступен.
                                              Ответить
                                              • Как pause узнает что он недоступен?
                                                тоже спросит доса?
                                                Ответить
                                                • Хорошая программа не срёт в память, которую не выделяла.

                                                  Да, в реальном режиме никто не может запретить срать в чужую память, кроме правил хорошего тона.
                                                  Ответить
                                      • >Можно захавать всю оперативку, доступную досовским программам
                                        я же не зря написал про тайни мод
                                        там все сегментные регистры указывают на один и тот же адрес. Я могу только офсетом вертеть
                                        Ответить
                                        • Нет. Так только на старте программы. Ты можешь направить сегментный регистр куда угодно.

                                          Как по-твоему COM-файлы читали состояние светодиодов Caps Lock, Num Lock, Scroll Lock из нулевого сегмента?
                                          Ответить
                                          • Действительно, вероятно ты прав
                                            и BDA небось тоже куда-то туда процерировалось далеко
                                            Ответить
                                            • Ну ещё COM-файлы срали в видеопамять, которая в другом сегменте.

                                              Модель TINY гарантирует только то, что CS=SS=DS на старте программы, а потом ты можешь крутить сегменты, как хочешь (в рамках разумного, конечно, чтобы ничего не сломать).
                                              Ответить
                                              • иными словами весь мой код, все мои данные, все мое должно влазить в 64К, а уже во время работы я могу куда угодно ходить (куда через адресацию дотянусь конечно)

                                                да, да?
                                                Ответить
                                                • Да, весь твой код + инициализированные переменные должны влезать в 64К. Да и неинициализированные тоже...

                                                  Потом ты можешь честно попросить ещё немного памяти через INT 21H, AH=48H и работать с полученным блоком, а можешь и нагло распидорашивать весь первый мегабайт оперативки, включая код самой «DOS» или, например, shadow copy видеобиоса (чтобы шрифты поменять).
                                                  Ответить
                                                  • Это какая-то новомодная хуйня:

                                                    The concept of a memory control block (MCB) was introduced in MS-DOS, Version 2.0

                                                    В нашем 1981-м году программист мог управлять всем мегабайтом памяти сам. Просто он должен был знать по каким адресам срать нельзя потому что там железки например.
                                                    Ответить
                                                    • Если в DOS 1.0 не было MCB, то и программу из программы вызывать было нельзя? Если память не размечена на свободную и занятую, то нельзя определить, куда можно загружать дочернюю программу и куда она может срать.

                                                      Или программы в DOS 1.0 использовали только ту память, которую им дали при старте, и больше никуда по соглашению не срали?
                                                      Ответить
                                                      • Да, вот я сейчас именно это и понял.

                                                        Можно конечно намутить свой диспетчер, но там той памяти все равно не хватило бы на две программы.

                                                        А так да: Волков коммандер не работает с устаревшими версиями дос))))
                                                        Ответить
                                                      • смотри что нашел
                                                        http://www.ctyme.com/intr/rb-2939.htm

                                                        У доса был execve/StartProcess ахахаха
                                                        Ответить
                                                        • >> 04h load and execute in background (European MS-DOS 4.0 only)

                                                          «European MS-DOS 4.0» –— это многозадачная версия «DOS», выпущенная по заказу «Siemens». Редкая вещь. Ни в файлообменниках, ни в P2P-сетях, ни на компакт-дисках я её не видел.
                                                          Ответить
                                                          • Вроде 4.0 ругали очень..

                                                            Как она многозадачная? Кооперативно и без виртуальной памяти?
                                                            Ответить
                                                            • Не знаю.

                                                              Для сравнения: «DR-DOS» поставлялся с программой «multitasker». Многозадачность была вытесняющей: программы он переключал принудительно по таймеру. Как было с памятью, не в курсе.

                                                              «MS-DOS» поставлялся с графической (но не оконной, а полноэкранной) оболочкой «DOSSHELL». У «DOSSHELL» был ручной переключатель задач: можно было запустить одну программу, поработать в ней, через «Alt+Tab» переключиться на другую, поработать в ней, потом переключиться обратно. Неактивную программу «DOSSHELL» мог высрать в своп-файл, чтобы сэкономить память («одновременно» запущенные программы всё равно друг друга не видели).

                                                              И это всё было в реальном режиме (или в V86, если был запущен EMM386). Хотя стоп, дурдосовский мультитаскер (в отличие от «DOSSHELL») работал только с EMM386, значит, виртуальный режим ему для чего-то был необходим.
                                                              Ответить
                                                              • А EMM386 это была реализация EMS через V86?

                                                                Какие вообще были способы заглянуть за первый мегабайт?
                                                                * A20
                                                                * XMS
                                                                * EMS
                                                                * DPMI
                                                                * Dos4GW
                                                                что-то еще?
                                                                Ответить
                                                                • Да, EMS переключал DOS с его приложениями в V86, а в диапазон адресов где-то между окошком видеопамяти и BIOS отображал окошко размером 32 или 64 килобайта в доступную ему оперативку. Вызовами API EMS это окошко можно было отображать на произвольный адрес, доступный защищённому режиму.

                                                                  XMS позволял оставлять DOS в реальном режиме и лишь при вызове API кратковременно переключался в защищённый режим, копировал нужный кусок памяти из памяти защищённого режима в память реального режима (т. е. куда-то в первый мегабайт) или обратно, а потом обратно переключался в реальный.

                                                                  Dos4GW –— это одна из реализаций DPMI (их было море).

                                                                  Была ещё такая штука:
                                                                  https://en.wikipedia.org/wiki/DOS_Protected_Mode_Services

                                                                  Использовалась редкими программами вроде Stacker/Doublespace/Drivespace (сжатие досовских дисков на лету) и некоторыми драйверами мыши.
                                                                  Ответить
                                                                  • Мне казалось что EMS и XMS это API для программистов (прерывания и их семантика)

                                                                    Они могли быть реализованы и без protected mode (то-есть до 286го, сиречь AT).

                                                                    Как?
                                                                    Например посредством карты в ISA разъеме которая имела DRAM память и ROM с реализацией XMS который она инсталлировала в известное прерывание.

                                                                    Там же бивис шароебился по памяти с шагом в четыре, кажется, K и искал другие биосы по сигнатуре (0xAA55 чи как-то так) и запускал их.
                                                                    Ответить
                                                                    • Возможно. Я описал лишь реализацию на 386+, которую видел.

                                                                      Я слышал про «expansion cards», но вживую их не видел. То ли EMS, то ли XMS как раз и эмулировали API этих карточек.
                                                                      Ответить
                                                                • Ещё был «нереальный» режим, который не рекомендовалось использовать (я видел только одну программу-демку, которая его использовала). Суть «нереального режима»: переключаемся в защищённый, ставим лимиты у всех сегментов по 4 гигабайта, возвращаемся в реальный и пишем в память за пределами первого мегабайта с помощью префикса длины адреса (добавляем 67H перед КОП).

                                                                  «Нереальный» режим почти никем не использовался, потому что такие программы были несовместимы с EMS, DPMI и с Windows.
                                                                  Ответить
                                                                  • Сколько же было костылей, ух.

                                                                    Представляю как первые линуксоиды и бздяшники смотрели на досеров (NT тогда еще не было).
                                                                    Ответить
                                                                  • > EMS, DPMI
                                                                    Да и хуй с ними. Зачем они тебе нужны если и так всю память видно? Ты же не собираешься её делить с другими прогами?

                                                                    > Windows
                                                                    А вот тут облом, да. Винда не даст переключиться в protected.
                                                                    Ответить
                                                                    • >> Зачем они тебе нужны если и так всю память видно?

                                                                      Затем, что программы, которым они потребуются, невозможно запустить в одном сеансе с программами «нереального» режима. Придётся перезагружать компьютер, чтобы перейти от программы одного режима к программе другого режима.
                                                                      Ответить
                                                              • > для чего-то
                                                                Чтобы не копировать первый мегабайт при каждом переключении контекста?
                                                                Ответить
                                                                • Вот и я об этом подумал.

                                                                  «Досшелл» не нужно быстрое переключение задач, поскольку там задачи переключаются по запросу пользователя. Он может работать и в реальном режиме, свопуя первый мегабайт на диск.

                                                                  «Мультитаскер» же с его многозадачностью реального времени должен переключаться быстро, поэтому он переходит в V86 и мапит первый мегабайт для каждого приложения на разные области расширенной памяти. Ему для переключения не надо копировать блоки памяти, достаточно только пошаманить с таблицей дескрипторов.
                                                                  Ответить
                                                        • Тут ещё упомянули «Desqview» –— это многозадачная оконная оболочка для досовских программ, по концепции похожая на «Windows 3.x». Эта оболочка ещё предоставляла API. Могла бы дорасти до полноценной ОС, но не сложилось.

                                                          Была ещё оболочка «GEM», которая тоже была внешне похожа на «Windows 3.x»...
                                                          Ответить
                                                          • Забавно что всё это не очень использовалось.
                                                            Как-то вот был dos, потом dos с win3.11, а потом сразу win95.
                                                            Ответить
                                                  • > Да и неинициализированные тоже
                                                    a equ byte [es:0000]
                                                    b equ word [es:0001]
                                                    Ответить
                                                    • Настоящий шаман, однако!

                                                      Для таких переменных не нужны фиксапы (потому что смещение фиксировано), если es тоже фиксирован либо вычисляется, а не указывает на саму программу. Поэтому такие переменные можно использовать даже в com-файле.
                                                      Ответить
                                                • P.S. Погугли макрос MK_FP, чтобы узнать, как в «Бройлер Си» дотягивались до чужих сегментов.
                                                  Ответить
                                                  • Я помню этот макрос и даже им пользовался
                                                    Модель памяти бройлер сцы я помню, все эти far, near и huge

                                                    но почему-то под дос я помню только засирание всей памяти без какой-либоп омощи со сотороны операционки

                                                    Я только теперь понял что до DOS 2.0 нельзя было запустить программу из программы, ахахха

                                                    Volcov не работао бы
                                                    Ответить
                                                    • До DOS 2.0 также не было директорий. В DOS 1.0 все файлы лежали в корне.

                                                      Представляешь файловый менеджер для такой системы?
                                                      Ответить
                                                  • Доктор Добсс в 1996 году писял что в MCB у каждого блока был PID (sic!!) того, кто его занял.

                                                    Конечно это был просто адрес PSP, но все же!
                                                    DOS -- многозадачная ОС
                                                    Ответить
                                                    • Может быть, но там не было никакой изоляции процессов, никакого планировщика.
                                                      Ответить
                            • Кстати, любители обмазываться "shared_ptr" и "unique_ptr" таким же образом могут соснуть?
                              Ответить
                              • AFAIK да, там надо std::weak_ptr (в свифте для этого есть weak или unowned)

                                но я не крестоблядь, пускай отцы расскажут
                                Ответить
                                • > я не крестоблядь
                                  Но всё верно рассказал же.

                                  weak_ptr помогает shared_ptr поддерживать граф владения ацикличным.

                                  А из unique_ptr просто не стоит лепить что-то сложнее дерева (т.к. он с weak не взаимодействует).
                                  Ответить
                                  • > weak_ptr, shared_prr, unique_ptr
                                    Блядь, как всё сложно... Именно поэтому я за "C".
                                    Ответить
                          • Интересно, а питоневский
                            a = []
                            a[0] = a
                            будет жить вечно?
                            Ответить
                            • Если я заменю батарейки.
                              Ответить
                            • Конечно же {}, со списком нада append, я перепутао.

                              Кстати, в 'J' значения всех типов неизменяемые, но можно делать циклические сцылки в локалях или объектах (которые основаны на локалях):
                              hui =: <'hui'
                                 na__hui =: hui
                                 hui
                              ┌───┐
                              │hui│
                              └───┘
                                 na__hui
                              ┌───┐
                              │hui│
                              └───┘
                                 na__na__na__na__na__hui
                              ┌───┐
                              │hui│
                              └───┘
                                 coclass 'petushara'
                                 petushara =: conew 'petushara'
                                 blyad__petushara =: petushara
                                 petushara
                              ┌─┐
                              │0│
                              └─┘
                                 blyad__petushara
                              ┌─┐
                              │0│
                              └─┘
                                 blyad__blyad__blyad__blyad__petushara
                              ┌─┐
                              │0│
                              └─┘
                              Ответить
    • > Что такое "int C::*"?
      https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members
      Это указатель на член класса C.

      > Как эта поебота работает?
      Магия — в выражении «sizeof(IsClassT<T>::test<T>(0)) == 1». Когда компилятор его встречает — он начинает искать перегрузку метода «test», которая может принять «0».

      Сначала компилятор пытается инстанцировать шаблонную функцию «One test(int C::*)» — принимающую указатель на целочисленный член класса C и возвращающую объект типа One.

      Если C — это класс, то объявление «One test(int C::*)» валидно, и компилятор рассматривает эту перегрузку. Он видит, что других подходящих перегрузок нет («test(...)» компилятор проигнорирует, поскольку имеется подходящая перегрузка с фиксированным числом параметров), а потому размер выражения «IsClassT<T>::test<T>(0)» будет равен размеру «One».

      Если C — это не класс, то объявление «One test(int C::*)» — это ошибка. Однако, по правилу SFINAE, компиляция не упадёт, а компилятор продолжит поиск подходящей перегрузки. Поскольку других объявлений «test» нет, будет выбран вариант с «...», а размер «магического выражения» станет равным двум (sizeof(Two)).
      Ответить
      • Простой пример SFINAE — это «std::enable_if», который реализован как-то так:
        template<bool B, class T = void>
        struct enable_if {};
         
        template<class T>
        struct enable_if<true, T> { typedef T type; };


        А используется так:
        #include <iostream>
        #include <type_traits>
         
        template<typename T>
        typename std::enable_if<(sizeof(T) > 4), void>::type isBig()
        {
            std::cout << "Yes! T is big!" << std::endl;
        }
         
        template<typename T>
        typename std::enable_if<(sizeof(T) <= 4), void>::type isBig()
        {
            std::cout << "No! T is tiny!" << std::endl;
        }
         
        int main()
        {
            isBig<char[42]>();
            isBig<char>();
         
            return 0;
        }
        Ответить
        • Какой тип возвращает isBig?
          Ответить
          • Если первый шаблонный аргумент (B) в enable_if равен true — то тот тип, который указан вторым аргументом в enable_if (T, в примере — void). Если же B == false, то никакой — в таком экземпляре enable_if не будет типа enable_if::type, получим ошибку компиляции, которая будет проигнорирована по правилу SFINAE.
            Ответить
        • А я понял. Если false, то type будет неопределён, и кусок не скомпилица.
          Ответить
      • > Если C — это класс, то объявление «One test(int C::*)» валидно

        Оно валидно, т.к. 0 кастится к нулевому указателю? А если не класс, то у него не может быть указателя на член?
        Ответить
        • Угу, причём содержимое класса неважно — достаточно того, что это класс.
          #include <iostream>
          #include <cstdlib>
           
          class C {
          	float pituh = 0.0f;  // Note: float
          };
           
          void func(int C::* ukozatel)
          {
          	std::cout << "Ukozatel == " << ukozatel << std::endl;	
          }
           
          // void func(int float::* ukozatel)
          // {
          // 	std::cout << "Ukozatel == " << ukozatel << std::endl;	
          // }
           
          /*
          prog.cpp:13:15: error: cannot combine with previous 'int' declaration specifier
          void func(int float::* ukozatel)
                        ^
          prog.cpp:13:20: error: 'ukozatel' does not point into a class
          void func(int float::* ukozatel)
          */
           
          int main()
          {
          	func(0);
          	return EXIT_SUCCESS;
          }

          https://ideone.com/u70mS9
          Ответить
    • Это указатель на любой член класса типа int.
      Ответить

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