Магистерский курс C++ (МФТИ, 2022-2023). Лекция 2. Шаблоны функций.

Поділитися
Вставка
  • Опубліковано 18 гру 2024

КОМЕНТАРІ • 52

  • @Минтай-ц5т
    @Минтай-ц5т 2 роки тому +42

    Уровень знания C++ - джун/миддл/сеньер/гуру/сидишь вечером один, читаешь стандарт и смеёшься

    • @vilture5706
      @vilture5706 4 місяці тому

      Есть книжка от Страуспа, Дизайн и Эволюция С++. В ней он сидит с чашкой кофе, вспоминает, как писали стандарт, ржет и пишет книгу.

  • @uvash4611
    @uvash4611 2 роки тому +19

    Утро начинается не с кофе...

  • @moddardtan5295
    @moddardtan5295 Рік тому +4

    Спасибо за все ваши видео с лекциями! Предоставляете редкую возможность на самообразование. Мегамегамощь! Спасибо!

  • @Ol5xHd0
    @Ol5xHd0 2 роки тому +6

    Смотрю N-ое видео от Константина по шаблонам. "Ну теперь-то я точно всё пойму." Где-то на тайминге в 1 час: "Так. Что? Перематываем в начало..."

  • @Batters99
    @Batters99 2 роки тому +3

    Отличная лекция, очень понятно объясняете! База, которую надо знать. Спасибо!

  • @jupel
    @jupel 2 роки тому +4

    Большое спасибо за лекции

  • @sergeykirdyankin7027
    @sergeykirdyankin7027 11 днів тому

    Так работает: template auto foo(){return n;}

  • @deleteddeleted1940
    @deleteddeleted1940 2 роки тому +5

    Слушаю лекции перед сном, чтобы от такого большого потока информации, которую нужно обработать, мозг перегрелся и вошёл в аварийную гибернацию. =)

  • @vladalu9794
    @vladalu9794 2 роки тому +1

    Очень полезный материал, спасибо большое за то что делитесь с нами.

  • @vladbelousov3934
    @vladbelousov3934 11 місяців тому

    Здравствуйте! Спасибо за лекцию. Вопрос про реализацию оператора сравнения строк (1:01). Будет ли правильной реализация не через специализации, а с использованием string_view?

  • @andrew_klygin
    @andrew_klygin 26 днів тому

    1:12:00 из любопытства набрал пример и удивился: компилятор его съел (arm clang 19) с "warning: use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions]"
    Пример компилируется всеми clang версии старше 8й, gcc от 5й (включая trunk) выдает вместе с ошибкой
    note: 'N::f' declared here
    3 | template int f(A*);
    Про оператор меньше понятней меньше всего. Я нашел только gcc 4й версии с таким сообщением: "error: expected primary-expression before 'int"
    сложно + непонятно :(

    • @tilir
      @tilir  23 дні тому

      Извините, не очень понятно что именно вы пробовали.
      Ошибка: godbolt.org/z/hTba8EbTT
      error: expected primary-expression before 'int'
      Починили: godbolt.org/z/svrzPEcff
      Всё это на gcc 14.

  • @DART2WADER
    @DART2WADER 2 роки тому +1

    1:12:31 На, возможно, нечто похожее есть мозговыносная лекция 03. Type loopholes in C++, Убербаг уровня стандарта - Антон Квятковский

  • @sergeykirdyankin7027
    @sergeykirdyankin7027 11 днів тому

    Можно ли как то получить Traits из переменной, например для deducing this - self как тип не прокатывает. decltype каждый раз дописывать не хочется))

  • @safocl9768
    @safocl9768 2 роки тому +2

    35:25 -- ну тут я думаю достаточно простой пример все же -- поскольку вызывая extern ты заверяешь компилятор, что где то там есть инстанцирование -- и он воспринимает енто за чистую монету, как если бы инстанцирование было на месте данного extern -- а коль енто так, то специализация следом ведет к ентой самой ошибке.

    • @wayydev
      @wayydev Рік тому

      Если я не ошибаюсь, то запрещаем инстанциирование конкретно в текущей единице трансляции, то есть априори не может быть "где-то там".
      Поправьте, если не так.

    • @justengineering1008
      @justengineering1008 4 місяці тому

      An explicit instantiation declaration (an extern template) skips implicit instantiation step: the code that would otherwise cause an implicit instantiation instead uses the explicit instantiation definition provided elsewhere (resulting in link errors if no such instantiation exists). This can be used to reduce compilation times by explicitly declaring a template instantiation in all but one of the source files using it, and explicitly defining it in the remaining file
      Skip - это skip, это не forbid IMHO

    • @IgorPolozov-uu5fn
      @IgorPolozov-uu5fn 2 місяці тому

      Согласен. Жаль, сначала написал коммент, а потом ваш прочёл.

  • @DART2WADER
    @DART2WADER 2 роки тому

    1:03:48 я везде свой код переписал на static inline. В некоторых случаях помогло удалить ненужные dummy.cpp с объявлениями статических полей.

    • @tilir
      @tilir  2 роки тому

      Обычно в C++ вы ставите либо static либо inline. Я остановлюсь на причинах этого позже. Но избежать определений статических переменных это в общем случае не поможет.

  • @ddvamp
    @ddvamp 2 роки тому +1

    1:11:04 Константин, эту проблему решили в С++20 (P0846R0: ADL and Function Templates that are not Visible)

    • @tilir
      @tilir  23 дні тому

      Да, действительно. Жаль, минус один красивый пример.

  • @СергейСергей-ч3ч6й

    Спасибо за лекцию.
    Комментарий насчёт первого примера, возведение в степень:
    Вы сразу же отмели наивный способ возведения в цикле. Но у этого способа есть одно неоспоримое преимущество - алгоритм работает для любого типа, для которого определена операция умножения, при этом никакие traits или инциализирующее значение для acc не нужны.

    • @tilir
      @tilir  2 роки тому

      Почему не нужны? А с чего вы начнете аккумулировать значения в линейном алгоритме? Всё то же, только медленней.

  • @dmitriikuchevskii9900
    @dmitriikuchevskii9900 Рік тому

    35:25 Я так и не понял, проблема в том что код не компилируется (что вроде как логично т.к полная специализация вызывает инстанцирование, которое явно запрещено) или в том что текст ошибки нелогичный?

    • @tilir
      @tilir  Рік тому

      Полная специализация вызывает инстанцирование? Это поворот. Я всегда думал она его заменяет. То есть компилятор начинает процесс инстанцирования только если НЕ видит полной специализации.

  • @Dima-Teplov
    @Dima-Teplov Місяць тому

    Интересно, а когда вы в конце предлагали попробовать самостоятельно написать гетерогенный максимум, то какой стандарт С++ имели ввиду?

    • @tilir
      @tilir  Місяць тому +1

      Пишите на каком сможете а далее идите вниз. Типа если получилось на C++11, попробуйте на C++98.

  • @yogthemuskrat
    @yogthemuskrat 2 роки тому +1

    Константин, спасибо за материал!
    Кажется, разделе про NTTP вы не упомянули указатели на члены класса, а это тоже интересное использование.

    • @tilir
      @tilir  2 роки тому +1

      Я по ряду причин отложил эту тему на будущее, но, раз уж вы её упомянули, может вы знаете полезные применения?

    • @yogthemuskrat
      @yogthemuskrat 2 роки тому +2

      ​@@tilir Странно, но мой предыдущий ответ пропал ( Может из-за ссылки на Godbolt.
      Но если коротко - один из вариантов использования, это хелпер-структура для получения значения поля у экземпларов класса.
      Что-то вроде:
      template
      struct member_getter
      {
      auto operator()(auto &&attr) const { return (attr.*Fn)({}); };
      };
      Mangled-ссылка на Compiler Explorer: godbolt_org/z/4x4sohMP6

  • @rouchy_
    @rouchy_ Рік тому +1

    А можете пожалуйста дать подсказку как найти пункт в стандарте который отражает инстанцирование шаблона при extern декларации, после чего нельзя делать специализацию?

    • @tilir
      @tilir  Рік тому

      Конечно могу. 13.9 и дальше в окрестностях 13.9.1.5.3 С++20
      "both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless the explicit instantiation follows a declaration of the explicit specialization"

    • @rouchy_
      @rouchy_ Рік тому

      ​@@tilir Ох, верно ли я понял, что конструкция из 13.9.3.2
      explicit-instantiation:
      extern(opt) template declaration
      вне зависимости от наличия extern является explicit-instantiation и поэтому мы не можем специализировать после неё?

  • @IgorPolozov-uu5fn
    @IgorPolozov-uu5fn 2 місяці тому

    extern специализация, это утверждение о том, что где-то специализация уже проведена. Компилятор не в праве этому не верить. При необходимости он отправит символ в таблицу импорта, а дальше пусть линкер разбирается. То есть, компилятор, вполне уверен, что специализация уже есть и не допускает повторной. Говорит он , достаточно внятно. Или я не прав?

  • @danielkeehl7450
    @danielkeehl7450 Рік тому

    37:15 "extern template означает не инстанцировать вообще ничего".
    Возникает резонный вопрос. Если extern template не инстанцирует ничего, то как остальные единицы трансляции найдут инстанцированное тело функции при линковке? Ведь явное инстанцирование, а значит и само скомпилированное тело функции, лежит в отдельном .cc файле, и при линковке это тело надо как-то найти, а значит остальным единицам трансляции на этапе компиляции должен быть виден прототип этой функции. А шаблоны - это механизм самого компилятора, и к линковке отношения не имеет. Из такой логики, как и из самого синтаксиса, extern template больше выглядит как инстанцирование прототипа функции, а не отсутствие инстанцирования в принципе. Или я где-то не прав?

    • @tilir
      @tilir  Рік тому

      Прототипы не инстанцируются. И если честно я просто не понял что вас смущает. Да, инстанцировать в данной единице трансляции отказываемся. Как раз и значит, что найдём в другой. Программа по стандарту состоит из нескольких tu, так что в какой-то степени стандарт про линковку знает.

    • @danielkeehl7450
      @danielkeehl7450 Рік тому

      @@tilir Просто непонятно, на что опирается линкер при поиске функции, если прототипа функции нет

  • @subzerod2
    @subzerod2 Рік тому

    acc=1;
    Можно заменить на acc = x/x;
    раз есть оператор*, можно надеяться и на обратный ему оператор/

    • @tilir
      @tilir  Рік тому +3

      Я бы и на вычитание не всегда надеялся. Сложение и умножение это очень частые вещи над чем угодно, включая, например, строки. Деление это операция немного странная.

  • @safocl9768
    @safocl9768 2 роки тому

    добрый день, а можно как нибудь сделать видео про варианты замены дефайнов для генерации разного кода?
    Ну например, в зависимости от ОС, или включения определенных компонентов программы.
    Просто получаетя, что с модулями енто невозможно теперь.
    Из предполагаемых мной вариантов можно применять меташаблонные функции (классы, структуры). Но возможно есть уже варианты более выгодных способов?

    • @tilir
      @tilir  2 роки тому

      У меня будет лекция про модули. Если вы видите конкретные причины по которым модули мешают условной компиляции, напишите их, я попробую их тоже разобрать.

  • @Marknegr
    @Marknegr Рік тому

    А почему в начальном примере «просто в цикле - плохая идея»?

    • @tilir
      @tilir  Рік тому +2

      Потому что простой цикл теряет информацию о том что вы хотите сделать. Загуглите: no raw loops.

  • @АлександрШепель-м5у
    @АлександрШепель-м5у 6 місяців тому +1

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

  • @alexanderkuzmenko987
    @alexanderkuzmenko987 3 місяці тому

    на 44:41 в аудитории чел просто камень:
    -- почему кстати ссылка на массив , а не указатель?
    -- ну , по правилам там скобочки ...

  • @dmitrylosev2064
    @dmitrylosev2064 2 роки тому

    20 слайд.
    "Как вы думаете, как играет запет инстанцирования со специализацией?"
    запет -> запрет
    29 слайд.
    int b = foo(a);
    Но foo возвращает void

  • @sigasigasiga
    @sigasigasiga 2 роки тому +1

    про гетерогенный максимум:
    1) если он consteval, то consteval auto max(T lhs, U rhs) { if constexpr(lhs < rhs) return rhs; else return lhs; }
    2) вернуть std::variant
    3) вернуть std::common_type

    • @tilir
      @tilir  2 роки тому

      (1) Это не будет работать. Внутри consteval функции lhs < rhs это всё равно не константное выражение.
      Но даже если поправить грубую ошибку, это всё равно не будет работать по очевидным причинам: godbolt.org/z/KqdjnG3cb
      (2) Это шутка была?
      (3) Попробуйте.