Konstantin Vladimirov
Konstantin Vladimirov
  • Видео 145
  • Просмотров 1 211 998
Практика языка C (МФТИ, 2023-2024). Завершение: вычислимость.
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики.
На этом семинаре мы начнём с обычного ассемблера и будем его упрощать. Сначала на этом пути мы получим RAM-модель, далее машину Минского ну и в конце машину Тьюринга. Где-то там, на том краю, где программирование уже смыкается с математикой, мы рассмотрим фундаментальные проблемы вычислимости и познакомимся с быстро растущими функциями.
Семинарист: Константин Владимиров.
Дата: 13 мая 2024 года.
Съёмка: Марк Гончаров.
Звук: Юлий Тарасов.
Предыдущий семинар: ruclips.net/video/Y_2uSYwQdtU/видео.html
Следующий семинар: нет, это последнее видео курса
Слайды к занятиям: cs.mipt.ru/wp/?page_id=7775
Гитхаб курса: github.com/tilir/c...
Просмотров: 4 924

Видео

Практика языка C (МФТИ, 2023-2024). Дополнение: SDL и визуализация
Просмотров 6 тыс.Месяц назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. Это дополнение к восьмому семинару, не обязательное, но мне кажется милым и интересным. Мы поговорим про использование библиотеки SDL для создания простых визуализаций и даже игр. Вы также получите уже не контестное а почти настоящее задание на подумать. Семинарист: Константин Владимиров. Дата: 6 мая 2024 года. Съёмка: М...
Практика языка C (МФТИ, 2023-2024). Семинар 8.2. Решение уравнений и вычисление функций.
Просмотров 4,4 тыс.Месяц назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. Вторая часть восьмого семинара посвящена решению уравнений. Мы начнём с того, что рассмотрим разнообразные сложности и ловушки плавающих чисел. Далее мы займёмся нахождением корней уравнений: сначала рассмотрим методы в которых надо сохранять брекетинг корня, потом уйдём от них в неизвестность. Ну и в конце нас ждёт прим...
Практика языка C (МФТИ, 2023-2024). Семинар 8.1. Матрицы и линейное программирование.
Просмотров 4,8 тыс.Месяц назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы начинаем последний логический семинар, посвящённый научным вычислениям. Мы разберёмся с матрицами, линейным программированием, захватим библиотеки BLAS и LAPACK и познакомимся с солверами на примере COIN-OR Linear Programming Solver. Семинарист: Константин Владимиров. Дата: 22 апреля 2024 года. Съёмка:...
Практика языка C (МФТИ, 2023-2024). Допсеминар: системы сборки (make, cmake).
Просмотров 14 тыс.Месяц назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. У студентов в самом разгаре проекты и настало время познакомиться с системами сборки. Мы начнём с разминки в виде анализа зависимостей между файлами. Очень быстро пройдя первый наивный способ собирать скриптом, мы за час напишем три версии makefiles возрастающей сложности. Ну а в конце нас ждёт немного cmake. Семинарист:...
Практика языка C (МФТИ, 2023-2024). Интермедия. Стандарт языка C.
Просмотров 16 тыс.Месяц назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы поговорим о стандарте C. Мы начнём с попытки изобрести очень простой язык программирования и увидим на его примере основные особенности поведения высокоуровневых программ. Далее мы подробно разберём разные формы поведения программ на языке C, познакомимся и потренируемся со стандартом языка. У нас буде...
Практика языка C (МФТИ, 2023-2024). Семинар 7.2. Конвейер.
Просмотров 5 тыс.2 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы окажемся максимально глубоко и решим сразу две интересных загадки. Первая приведёт нас к концепции конвейера, на которой мы остановимся и внимательно её изучим. Вторая же приведёт нас к ещё более удивительным открытиям, касающимся истинной природы кешей. Семинарист: Константин Владимиров. Дата: 8 апрел...
Практика языка C (МФТИ, 2023-2024). Семинар 7.1. Кеши и немного о бенчмаркинге.
Просмотров 6 тыс.2 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы погрузимся в реальный мир. Начнём с простого бенчмаркинга и особенностей поведения оптимизирующих компиляторов, разберёмся с макросами, а потом встанем перед загадкой связанной с произведением матриц и решим её. Семинарист: Константин Владимиров. Дата: 1 апреля 2024 года. Съёмка: Марк Гончаров. Звук: Ю...
Практика языка C (МФТИ, 2023-2024). Семинар 6.5. Кросс-ассемблеры, их сходства и различия.
Просмотров 4,6 тыс.2 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. Это занятие посвящено тому чтобы показать как похожи на самом деле различные ассемблеры и как различны похожие концепции. Мы рассмотрим ассемблеры ARM и RISCV, идею линк-регистра, постиндексную адресацию, жизнь без регистра флагов, векторизацию и прочее. В конце после обзора литературы не выключайте, будет бонус про рело...
Практика языка C (МФТИ, 2023-2024). Семинар 6.4. Представления плавающих чисел и ассемблер x86.
Просмотров 4,3 тыс.2 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы попробуем осознать сложность представления вещественных чисел, познакомимся со стандартом IEEE754, посмотрим на два способа работы с плавающими числами в ассемблере x86 и даже обсудим влияние на оптимизации. Параллельно будет введена концепция строгого алиасинга: в будущем она нам сильно пригодится. Се...
Практика языка C (МФТИ, 2023-2024). Семинар 6.3. Вызовы функций в ассемблере x86 и ABI.
Просмотров 5 тыс.3 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы займёмся вызовами функций и познакомимся с основными концепциями ABI: работой со стеком, caller и callee saved регистрами и конвенциями передачи аргументов. Во второй половине мы немного обсудим инлайн-ассемблер и сформулируем главное правило разработки на ассемблере. Семинарист: Константин Владимиров....
Практика языка C (МФТИ, 2023-2024). Семинар 6.2. Условные переходы и память в ассемблере x86.
Просмотров 15 тыс.3 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы погрузимся в работу с флагами. Мы начнём с того что обсудим детали goto. Далее вспомним кодировку для целых чисел. Далее мы увидим как отличаются знаковые и беззнаковые сравнения. Потом мы познакомимся с концепцией "эффективного адреса" и научимся работать с памятью. В конце нас ждёт погружение в тёмны...
Практика языка C (МФТИ, 2023-2024). Семинар 6.1. Изобретаем ассемблер.
Просмотров 20 тыс.3 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы начнём своё путешествие в ассемблер. Для начала мы изобретём свой собственный несложный ассемблер и даже потренируемся писать для него кодировщик и декодер инструкций. Далее мы посмотрим на более взрослый x86 его регистры и систему команд. Я также устрою большой сеанс live-coding и в конце мы подумаем ...
Практика языка C (МФТИ, 2023-2024). Семинар 5.3. Динамическое программирование.
Просмотров 4,9 тыс.3 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы познакомимся с принципом оптимальности Беллмана и дискретным динамическим программированием. Мы решим несколько классических задач: рюкзак, размен монет, расстояние редактирования в строках. Кроме того мы ещё немного сдвинем пределы регулярности и выясним связь формальных грамматик как с регулярными вы...
Практика языка C (МФТИ, 2023-2024). Семинар 5.2. Регулярные выражения и автоматы.
Просмотров 4,6 тыс.4 месяца назад
Практические занятия по языку C на первом курсе МФТИ. Кафедра информатики. На этом занятии мы погрузимся в более интересную обработку строковой информации. Вы познакомимся с понятиями конечного автомата и регулярного выражения, поиграем с утилитой grep, научимся писать наши собственные регулярные выражения на C и даже используем их для условно-практических задач (скажем распознавания email в те...
Практика языка C (МФТИ, 2023-2024). Семинар 5.1. Строки и символы.
Просмотров 6 тыс.4 месяца назад
Практика языка C (МФТИ, 2023-2024). Семинар 5.1. Строки и символы.
Практика языка C (МФТИ, 2023-2024). Семинар 4.3. Структуры данных.
Просмотров 4,2 тыс.5 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 4.3. Структуры данных.
Практика языка C (МФТИ, 2023-2024). Семинар 4.2. Обходы деревьев.
Просмотров 4,6 тыс.6 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 4.2. Обходы деревьев.
Практика языка C (МФТИ, 2023-2024). Семинар 4.1. Односвязные списки.
Просмотров 4,9 тыс.6 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 4.1. Односвязные списки.
Практика языка C (МФТИ, 2023-2024). Интермедия: командная строка, файлы и вариабельные аргументы.
Просмотров 4,6 тыс.6 месяцев назад
Практика языка C (МФТИ, 2023-2024). Интермедия: командная строка, файлы и вариабельные аргументы.
Практика языка C (МФТИ, 2023-2024). Семинар 3.3. Цифровые сортировки.
Просмотров 3,4 тыс.7 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 3.3. Цифровые сортировки.
Практика языка C (МФТИ, 2023-2024). Семинар 3.2. Стратегия "разделяй и властвуй".
Просмотров 4,4 тыс.7 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 3.2. Стратегия "разделяй и властвуй".
Практика языка C (МФТИ, 2023-2024). Семинар 3.1. Линейный поиск и простые сортировки.
Просмотров 5 тыс.7 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 3.1. Линейный поиск и простые сортировки.
Практика языка C (МФТИ, 2023-2024). Углубление пройденного: логическая память и виртуальная память.
Просмотров 8 тыс.7 месяцев назад
Практика языка C (МФТИ, 2023-2024). Углубление пройденного: логическая память и виртуальная память.
Практика языка C (МФТИ, 2023-2024). Семинар 2.3. Время и случайность.
Просмотров 4,7 тыс.8 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 2.3. Время и случайность.
Практика языка C (МФТИ, 2023-2024). Семинар 2.2. Побитовые вычисления.
Просмотров 6 тыс.8 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 2.2. Побитовые вычисления.
Практика языка C (МФТИ, 2023-2024). Семинар 2.1. Простые числа.
Просмотров 8 тыс.8 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 2.1. Простые числа.
Практика языка C (МФТИ, 2023-2024). Допсеминар: unix shell
Просмотров 15 тыс.8 месяцев назад
Практика языка C (МФТИ, 2023-2024). Допсеминар: unix shell
Практика языка C (МФТИ, 2023-2024). Семинар 1.3. Числа Фибоначчи.
Просмотров 7 тыс.8 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 1.3. Числа Фибоначчи.
Практика языка C (МФТИ, 2023-2024). Семинар 1.2. Системы счисления.
Просмотров 11 тыс.9 месяцев назад
Практика языка C (МФТИ, 2023-2024). Семинар 1.2. Системы счисления.

Комментарии

  • @ddvamp
    @ddvamp 44 минуты назад

    1:18:12 experimental до сих пор на слайдах 1:20:22 Почему бы просто не вернуть suspend_tunable{is_cancelled}?

  • @ddvamp
    @ddvamp 22 часа назад

    1:08:42 Константин, разве это эквивалентное преобразование? Ведь мьютекс обеспечивает видимость записи в resptr, значит в p также должна быть запись в ложной ветви строки 4

  • @ddvamp
    @ddvamp День назад

    1:14:43 Константин, ниже писали про ошибку в алгоритме. В текущих слайдах она всё ещё присутствует

  • @FeelUs
    @FeelUs День назад

    17:00 разве при undefined instruction exception операционка не посылает какой-нибудь сигнал (который можно перехватить)?

  • @DmitryKandiner
    @DmitryKandiner День назад

    1:29:35 За что Херб Саттер ни возьмётся Всё превращается в ничто А если он за void берётся То просто тратит меньше сил.

  • @alex_s_ciframi
    @alex_s_ciframi 2 дня назад

    спасибо :)

  • @shabnakadyr1564
    @shabnakadyr1564 2 дня назад

    Чудесный курс, большое спасибо. С удовольствием прослушал и порешал задачки

  • @user-qu9pq6sw6k
    @user-qu9pq6sw6k 2 дня назад

    Я человек простой: Увидел ролик Константина Владимирова, автоматически поставил лайк. Цикл лекций шикарен❤ Пошел штурмовать магистерский курс🙂

  • @alex_s_ciframi
    @alex_s_ciframi 2 дня назад

    Константин, спасибо за лекцию. 47:44 - опечатка "рещить" 1:18:31 - а такое приведение к float* - это разве не нарушение стрикт алиазинг?

  • @croessmah6671
    @croessmah6671 2 дня назад

    "etx - почему-то сердечком". etx, eot, enq, ack - это символы для карточных мастей.

  • @DanielPinchuk
    @DanielPinchuk 3 дня назад

    37:00 "...emplace возвращает итератор и признак. Если признак - false, то итератор невалидный". Нет, это не так. Итератор всегда валидный, и указывает либо на вновь созданный элемент, либо на элемент, который уже был в мапе. Также не уверен, что operator[] два раза ищет элемент в мапе, т.к. это не имеет смысла, учитывая то, как работает emplace (и insert) Про обязательный конструктор по умолчанию, который требует этот оператор, я не знал, спасибо :)

  • @dsorvq
    @dsorvq 3 дня назад

    Здравствуйте! На 34:08 говорится, что мы можем делегировать конструктор и продолжить список инициализации, при условии, что вызываемый конструктор стоит на первом месте. Однако, код со слайда не компилируется (второй конструктор некорректный). Вот что написано в cppreference: If the name of the class itself appears as class-or-identifier in the member initializer list, then the list must consist of that one member initializer only; Как я понимаю, лучшее, что мы можем сделать - это "немного развернуть делегирование" и из конструктора с меньшим числом аргументов, вызывать конструктор с большим их числом.

  • @alex_s_ciframi
    @alex_s_ciframi 3 дня назад

    1:14:11 - отвечу за студентов)) designated-initializer-list [i] - элемент массива по данному индексу заполняется. А дальше в списке от него пляшется. В итоге, в начале 1,3,5 , в конце 8,4,2, а в середине нули 1:14:11 - и опечатка в енуме есть - точка с запятой не там :)

  • @alex_s_ciframi
    @alex_s_ciframi 4 дня назад

    Константин, спасибо за лекцию. 6:33 - а разве $ нельзя в именах идентификаторов в C и C++ ? GCC, GDB, студия - позволяют. Хотя, на cpprefrence доллар не упомянут, вообще говоря

  • @alex_s_ciframi
    @alex_s_ciframi 4 дня назад

    Константин, спасибо за лекцию. 19:44 - так, ежели это отсортировать, то if становится не нужен )

  • @ddvamp
    @ddvamp 4 дня назад

    43:10 Константин, возможно стоит убрать повсеместно на слайдах указание типа мьютекса у guards, перейдя на CTAD? Или же вы таким образом ещё и показываете, какой именно мьютекс используется в примере?

  • @alex_s_ciframi
    @alex_s_ciframi 4 дня назад

    Константин, спасибо за лекцию. 48:06 - а можно ведь не маллок делать, а вторую матрицу по месту транспонировать, а после вычислений вернуть обратно. Так будет даже шустрее, наверное. Понимаю, что входной параметр менять - это так себе решение, но этот момент можно отразить в документации к функции

  • @Michael-Solo
    @Michael-Solo 4 дня назад

    на слайдах 60 и 61 разве нет ошибки в функции копирования? Там же должно быть с какого указателя по какой и в какой копируем то есть std::copy(rhs.p_, rhs.p_ + n_, p_);

  • @user-vm7mk7mq9p
    @user-vm7mk7mq9p 4 дня назад

    Здравствуйте! Домашние задания это внутренний ресурс только для студентов, или не-студентам тоже можно зарегистрироваться посмотреть?

    • @tilir
      @tilir 4 дня назад

      Открыто пока что для всех. Ссылка в описании.

  • @FeelUs
    @FeelUs 4 дня назад

    gprof на каждый запрос "ты где?" получает в виде ответа функцию. А существует ли инструмент, который на каждый запрос "ты где?" получает стек функций чтобы правильно посчитать веса call-графа, и при этом не симулирует программу, как это делает callgrind?

  • @FeelUs
    @FeelUs 4 дня назад

    1:28:00 ещё не придумали способ, как откатиться на шаг назад, чтобы заново не запускать программу?

  • @alex_s_ciframi
    @alex_s_ciframi 4 дня назад

    Константин, спасибо за очередную шикарную лекцию. У меня книжка Юрова, 2-е издание всё ещё лежит, я ещё в универе её приобрёл )) Как сокровище лежит. Она прям такая красивая, как игрушка была в магазине :D

  • @ddvamp
    @ddvamp 5 дней назад

    52:40 Несколько интересно, что можно хранить указатель никак не связанный с подконтрольным, а также в принципе не обладать каким-либо объектом: struct S {}; S obj; std::shared_ptr<S> s(std::shared_ptr<S>{}, &obj); // хранит адрес obj не владея им И оказывается weak_ptr тоже хранит указатель, сохраняя алиасинг

  • @ddvamp
    @ddvamp 6 дней назад

    7:55 Внезапно понял окончательно, почему повсеместно в стандарте в шаблонном коде используется формат direct-initialization против list-initialization Ну подумаешь, отдаётся приоритет list конструкторам, так здесь же объект инициализируется таким же объектом, копирование на лицо. А потом приходит человек с таким классом struct S { S() = default; S(S const &) { std::cout << "copy"; } S(std::initializer_list<S>) { std::cout << "list"; } }; и спрашивает, почему у него всё сломалось? Счастливой отладки!)

  • @ddvamp
    @ddvamp 6 дней назад

    1:07:25 Всё ещё на слайдах

  • @user-rn5oj5tl4h
    @user-rn5oj5tl4h 6 дней назад

    Каждый раз во время викторины всё больше ужасаешься языку и всё больше хочется досмотреть до конца.

  • @user-fc6gl2vm5i
    @user-fc6gl2vm5i 6 дней назад

    не подскажите как перейти к контесту, до этого начинал решать, а теперь не могу снова зайти

    • @tilir
      @tilir 5 дней назад

      Есть в описании видео: olymp1.vdi.mipt.ru/

    • @user-fc6gl2vm5i
      @user-fc6gl2vm5i День назад

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

  • @ddvamp
    @ddvamp 6 дней назад

    1:10:00 Константин, правильно ли я понимаю, что здесь срабатывает "A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule" из С++20 и "The result of the search is the declaration set of S(M,T). If it is an invalid set, the program is ill-formed. If it differs from the result of a search in T for M in a complete-class context ([class.mem]) of T, the program is ill-formed, no diagnostic required." ([basic.lookup#class.member.lookup-6]) из С++23? Если это так, за что же балл обещался?)

  • @ddvamp
    @ddvamp 7 дней назад

    47:00 Константин, здесь явно UB. Предположим, что в deallocate пришел указатель T *, который в действительности указывает на объект типа T. Тогда reinterpret_cast<node *>(ptr) даст указатель node *, который всё ещё указывает на объект типа T, строго по правилам преобразования указателей ([basic#compound-5], [expr.reinterpret.cast#7], [expr.post#expr.static.cast-14]). Да и в принципе, если значение указателя не "указывает на что-то, pointer-interconvertible с node", оно останется неизменным, только тип поменяется. В следующей строке (88) мы сразу делаем обращение к объекту (node), не являющегося type-accessible [expr#basic.lval-11], получая UB Первым шагом к исправлению было бы заменить aligned_storage (который с С++23 deprecated), на T. Тогда, если гарантировать, что в deallocate приходят только указатели, выделенные аллокатором, благодаря pointer-interconvertible сможем получать указатель на node Вторым шагом было бы заменить выделение блока памяти на массив из node, чтобы сразу начать жизнь объектов node. Это просто сделать, добавив полю next инициализатор, сделав union implicit-lifetime type Скорее всего нужно будет сделать еще что, но для этого нужно более подробно шерстить стандарт. Ну и разумеется, всё ещё ждём завоза в компиляторы std::start_lifetime_as и std::is_implicit_lifetime

    • @tilir
      @tilir 5 дней назад

      Мне нравится использование вами слова "явно" в задачке которую не могут решить поколения магистрантов. Явно, ага ))

  • @ddvamp
    @ddvamp 7 дней назад

    1:20:05 Это не так, parameter и return type могут быть неполными даже при использовании по значению в объявлении функции, главное чтобы они были определены к моменту, когда будет нужно определение функции. См. CWG-1824 и CWG-2430. Простой контрпример struct S { static S create() { return {}; } // incomplete S &operator= (S s) {} // incomplete }; Более того, поскольку класс шаблонный, и функции будут инстанцироваться по запросу, можно написать определение функций прямо на месте iterator begin() { return iterator{*this}; } sentinel end() { return sentinel{ranges::end(snd_)}; } P.S. Возможно, интересный пример struct S { class C; C foo() { return {}; } class C {}; // ok }; // class S::C {}; // too late, return type is incomplete

  • @DmitryKandiner
    @DmitryKandiner 7 дней назад

    Возможно, purview -- зона действия?

  • @ddvamp
    @ddvamp 8 дней назад

    1:23:50 Константин, можете подсказать, на что вы здесь ссылаетесь? Я только смог понять, что ограничения проверяются когда в стандарте явно прописано "constraints are (not) satisfied", и это сделано во многих местах. Как я вижу, здесь ограничения проверяются на втором этапе инстанцирования, что для templated функций откладывается до их использования. #include <iostream> template <typename T> struct S { struct R { void foo() requires (T::value) {} // ok before use }; void foo() requires (T::value) {} // ok before use T &bar() requires (T::value) {} // error cause reference to void }; int main() { S<void> s; return 0; } При этом при разрешении перегрузки на первом этапе инстанцирования? #include <iostream> template <typename T> struct S { void foo(int *) requires (false) { T &t = T(); } void foo(int) requires (true) {} }; int main() { S<void> s; s.foo(42); return 0; }

  • @ddvamp
    @ddvamp 8 дней назад

    30:55 Константин, разве проектор &S::x должен быть бесплатным? Я полагаю, разница между a.x и a.*(&S::x) как разница между прямым и косвенным вызовом функции. Т.е. проектор несёт в себе некую runtime информацию, как обратиться к полю. Если заменить на [](const auto &v) { return v.x; }, то разницы в скорости не будет. P.S. Как-то пару лет назад я под каким-то видео оставлял комментарий, что (по моему наблюдению) компиляторы не оптимизируют в алгоритмах STL косвенные вызовы, и что функции суррогатного вызова не являются бесплатными. Здесь похоже та же ситуация

  • @ddvamp
    @ddvamp 9 дней назад

    На первый взгляд deducing this кажется великолепным нововведением, однако если начать им пользоваться, обнаруживаешь, что здесь работают всё те же правила языка и нет никакой магии. Хорошо работает deducing this лишь тогда, когда ты не предполагаешь наследования. Почему? По сути члены с явным this являются статическими шаблонами, которые имеют доступ лишь к своему классу. К наследнику доступа уже нет, если только не объявить дружбу. Таким образом explicit object функции не поместишь просто так в базовый класс Impl/Base для реализации SRP. Во-вторых, если проблема доступа решена, для каждого наследника будут генерироваться свои версии функции, даже если это просто доступ к члену базы (геттер). Хотелось бы новый механизма языка, чтобы не плодить множество идентичных по содержанию специализаций шаблона. К тому же, с лямбдами есть какие-то проблемы в поиске имён/выводе типов/разрешении перегрузки. То ли это баги, то ли таков стандарт (я не читал ничего про deducing this, так что не могу мотивировать). #include <iostream> #include <variant> template <typename ...Ts> struct overloaded : Ts... { using Ts::operator()...; }; struct Leaf {}; struct Node; using Tree = std::variant<Leaf, Node *>; struct Node { Tree left, right; }; struct LeafCount { int operator() (Leaf) noexcept { return 1; } }; int num_leaves(Tree const &tree) { return overloaded{//[](Leaf) { return 1; }, // not selected LeafCount{}, // selected [](this auto &&self, auto &v) { if (std::holds_alternative<Leaf>(v)) { return self(std::get<Leaf>(v)); } else { auto &n = std::get<Node *>(v); return self(n->left) + self(n->right); }}}(tree); } int main() { Tree tree; std::cout << num_leaves(tree); return 0; } И более простой пример: #include <iostream> template <typename ...Ts> struct overloaded : Ts... { using Ts::operator()...; }; struct ForInt { void operator() (int) { std::cout << "int"; } }; int main() { overloaded{[](int) { std::cout << "int"; }, // infinite recursion //ForInt{}, // ok [](this auto &&self, auto v) -> void { self(v); }}(42); return 0; } Если подумать, возможно всплывут другие неприятности с применением этой техники. Edit: Примеры выше не работают, поскольку лямбды const, что требует преобразования неявного this. Если добавить mutable, всё чинится.

  • @ddvamp
    @ddvamp 9 дней назад

    1:08:10 Константин, возможно вы видели, есть пропосал нового statement в язык для итерирования по tuple-like объектам (а также объектам классов) в compile-time: P1306R2 Expansion statements P.S. Немного пробежавшись глазами по документу, я увидел, что ведутся обсуждения по добавлению в язык возможности итерироваться по пачкам, что довольно круто. Но всё же, через pack indexing можно было бы задать индексы, которые я хочу пробежать

  • @ddvamp
    @ddvamp 9 дней назад

    1:06:25 Константин, "This parrot is no more!". forward_as_tuple пораждает набор (!) ссылок, что противоречит исходной задаче: передать xvalue по значению. Поэтому, при передаче в foo prvalue, лямбда переживёт их. Пример: #include <iostream> #include <tuple> struct Parrot { ~Parrot() { std::cout << "Parrot is dead"; } }; int main() { auto foo = []<typename ...T>(T &&...t) noexcept { return [a = std::forward_as_tuple(std::forward<T>(t)...)] mutable noexcept { (void) std::get<0>(a); }; }; [[maybe_unused]] auto l = foo(Parrot{}); std::cout << " before use"; return 0; } Правильный способ состоит в ручном конструировании tuple: [a = std::tuple<T...>(std::forward<T>(t)...)], причём нельзя полагаться на CTAD (выведет всё как значения) Стоит отметить, что допустимо использовать T и в теле конструируемой лямбды: [&a = t] { std::forward<T>(a); }, поэтому, если мы уверены, что все инициализаторы переживут объект замыкания, а особенно с С++26 (Pack Indexing: P2662R3), можно делать так: auto foo = []<typename ...T>(T &&...t) noexcept { return [&] noexcept { (void) std::forward<T...[0]>(t...[0]); } } что, правда, немного многословнее нежели std::get<0>(t) для tuple P.S. Как жаль, что в pack indexing не завезли выражения: std::forward<T>(t)...[0]

  • @ddvamp
    @ddvamp 9 дней назад

    12:25 Константин, что именно вы подразумеваете под Callable? Стандарт однозначно задаёт function object type [function.objects] и callable type [function.objects#func.def-3]. P.S. Минорно, но к function object type (слайд 5) ещё относятся ссылка на функцию, а также класс с приведением к ссылке на функцию или к ссылке на указатель на функцию

  • @ddvamp
    @ddvamp 9 дней назад

    3:31 Но это не так, согласно стандарту "The closure type for a lambda-expression has a public inline function call operator..." ([expr.prim.lambda#closure-4], [expr.prim.lambda#closure-9]). Иначе бы не работала идиома overloaded: template <typename ...Ts> struct overloaded : Ts... { using Ts::operator()...; } (Edit 2: Да, начиная с С++20 здесь не нужно правило вывода, поскольку оно генерируется неявно: CTAD for aggregates) Также можно проверить так ([]{}).operator()(); Edit: Увидел позже по лекции, что вы, Константин, об этом узнали, однако в лекции следующего года и в текущих слайдах всё осталось без изменений, поэтому оставлю комментарий Интересно то, что по стандарту эти две функции не обязаны делегировать одной и той же реализации, только если не указать static (С++23) для operator(). P.S. Известным вам, Константин, способом можно обойтись без decay_t на 4 слайде: decltype(+func). Получается позитивная функция)

  • @ddvamp
    @ddvamp 9 дней назад

    1:23:17 Оставлю для себя и зрителей: строго по стандарту, pack, который не расположен в конце параметров функции, является невыводимым контекстом ([temp.deduct.call#1.sentence-7], [temp.deduct.type#5.8]). То есть формально здесь невозможно вывести типы из аргументов. И если их указать явно, всё будет в порядке, !НО не в случае конструктора, который нельзя вызывать напрямую

  • @ddvamp
    @ddvamp 9 дней назад

    47:10 Только что выяснил, что в С++23 сделали deprecated наличие пробела между "" и _ в названии оператора (CWG-2521. User-defined literals and reserved identifiers). На данный момент повсеместно используется на слайдах

  • @ddvamp
    @ddvamp 10 дней назад

    37:07 Константин, прошу прощения, но объектов типа void быть не может, поскольку это не объектный тип. Более точно, он является incomplete type, а объекты такого типа нельзя определить ([basic.types.general#5.sentence-2], [basic.def#5]). Использование выражения типа void заложено в стандарте в пунктах про comma operator и return statement, и это интересно: Категория выражения у void() prvalue, ничего не инициализирующее ([expr.type.conv#2.sentence-2]). Левый операнд оператора запятая (когда он встроенный) является discarded-value-expression ([expr.comma#1.sentence-2]). Temporary materialization в discarded-value-expr происходит лишь для prvalue объектного типа ([expr.prop#expr.context-2.sentence-6]). Если же void() правый операнд запятой, то тип всего выражения prvalue void ([expr.comma#1.sentence-4]). И согласно [stmt.return#2.sentence-3] операндом в return может быть void-expression, то есть prvalue void Edit: Также в определении prvalue ([expr#basic.lval-1.2.sentence-1]) отдельно выделен тип void, а определение glvalue ([expr#basic.lval-1.1.sentence-1]) как бы продолжает мысль ("...is an expression whose evaluation...")

    • @tilir
      @tilir 10 дней назад

      Вы сами себе противоречите. С одной стороны не может быть, а с другой стороны заложено в стандарте, значит может быть. Я собственно над этим и смеюсь в лекции )) Это примерно как с nullptr dereference -- нигде нельзя, а в typeid можно. P. S. спасибо что отсматриваете и систематично комментируете курс, я всё вижу и поотвечаю как будет время. Это очень ценно.

    • @ddvamp
      @ddvamp 10 дней назад

      ​@@tilir говоря "заложено", я скорее имел ввиду что везде в стандарте выражение типа void и его использование прописано как краевой случай. Если вы говоря про объект так пошутили, то я не понял P.S. Вы возможно видели, но в С++26 наконец задокументировали, что разыменование null pointer value ведёт к UB (кроме typeid) CWG-2823. Implicit undefined behavior when dereferencing pointers P.S.S. Слова про противоречие самому себе тоже чтоли шутка? Сложно)

  • @ddvamp
    @ddvamp 10 дней назад

    22:30 По хорошему, функтор тоже нужно форвардить (либо использовать std::move, если мы его построили в контексте оболочки). Это необходимо, поскольку у функтора может быть перегруженный оператор функционального вызова для xvalue, более оптимальный чем для lvalue Edit: Увидел, что данный шаг производится далее после введения лямбд

  • @requ1em939
    @requ1em939 11 дней назад

    Спасибо огромное за то, что выкладываете подобные семинары. Очень приятно и поучительно Вас слушать.

  • @ddvamp
    @ddvamp 11 дней назад

    16:47 Константин, к сожалению здесь вы не совсем правы: "In C++ class and array prvalues can have cv-qualified types. This differs from ISO C, in which non-lvalues never have cv-qualified types." ([expr#footnote-45]). Согласно [conv.rval] const prvalue (типа класса) материализуется в const glvalue, что и происходит при инициализации ссылки от prvalue. ([dcl.init.ref#5.3]) Пример #include <iostream> struct S {}; void foo(S &) { std::cout << '1'; } void foo(S &&) { std::cout << '2'; } void foo(S const &) { std::cout << '3'; } void foo(S const &&) { std::cout << '4'; } S const bar() { return {}; } int main() { foo(bar()); // 4 return 0; } И разумеется, если оставить только 1 и 2, получим сообщение об ошибке о потере const квалификатора

  • @ddvamp
    @ddvamp 11 дней назад

    1:16:37 Указатель на ссылку сформировать нельзя, так что подозреваю, что они не являются эквивалентными (или неправильно подозреваю?) #include <iostream> template <typename T> constexpr bool Atomic = true; template <typename T> concept C = Atomic<T>; template <typename T> concept D = Atomic<T *> && true; void foo(C auto &&) { std::cout << '1'; } void foo(D auto &&) { std::cout << '2'; } int main() { int x = 42; foo(x); // 1 return 0; }

  • @user-yy6ig3wm2h
    @user-yy6ig3wm2h 11 дней назад

    Большое спасибо, очень информативно

  • @ddvamp
    @ddvamp 11 дней назад

    58:27 К сожалению, согласно [expr.prim.req.compound] после -> может стоять лишь концепт. Необходимо писать -> same_as<T::inner>, что продемонстрировано в примере ниже по тексту стандарта P.S. Ниже уже обращали внимание на это, но оставлю комментарий, поскольку на слайдах это всё ещё не исправлено P.S.S. 1:06:17 Концепт SomeConcept с 42 слайда так же не исправлен. Должно быть SomeConcept<U...> T -> SomeConcept<T, U...> Edit: Позвольте также отметить, что момент 1:07:50 в новой черновой лекции так и не был поправлен, здесь специализация: "A class or variable template declaration of a simple-template-id declares a partial specialization ([temp.spec.partial])." ([temp#pre-note-3])