TGViewer
this->notes. this->notes. @thisnotes · 4.52K subscribers
Post #204 1.71K
#cpp

Посмотрел доклад Andrei Alexandrescu на CppCon 2021. Накидаю приконых фактов оттуда:
- предлагает засунуть в стандарт

template <typename… Ts> struct type_sequence {};

потому что если этого не сделать, каждый будет писать это сам (и вероятно с помощью tuple/variant, что концептуально не всегда то, что нужно). В таком виде со списками типов предлагали работать и на CppRussia 2019 с примерами других функций, которые могут понадобиться при работе со списками типов, что выглядит вообще-то довольно приятно и в ногу со временем. И рядом Alexandrescu предлагает три базовые функции в классической манере для работы с металистом типов: head, tail и cons (создать лист из элемента и другого листа). Всё как в Lisp.

- и депрекейтнуть integer_sequence, потому что это не последовательность целых чисел, а последовательность значений какого-то типа. Вместо него ввести value_sequence, потому что это семантически честнее.

Из интересного ещё можно отметить такое. Предположим есть функция

template <typename T, typename… Ts, typename U>
int f(T, U, const Ts&…);


и её вызовы

f(1, 2); // Ts=<>
f<int, int>(1, 2, 3); // Ts=<int>
f<int, int, double>(1, 2, 3, 4); // Ts=<int, double>


Тип U всегда сможет вывестись! Причём из параметра, а не указанного списка типов в шаблоне. В первом случае это int по понятным причинам. Во втором это тоже int. В третьем же Ts выводится как <int, double>, а U — исходя из параметра. Причина в том, что если variadic pack начал матчится, он не остановится и идёт до конца (жадный матчинг). Получается, в таком кейсе у нас нет возможности указать тип U компилятору явно, ведь он всегда будет выводится из параметра.

Соответственно, если у вас есть что-то такое

template <typename... Ts, typename T = int>
T f(Ts…);


тип T может быть только int, потому что в него никогда ничего не сматчится.

Соответственно, если у вас пак типов функции находится не в конце, то он всегда должен быть указан явно:

template <typename... Ts, typename T>
int f(Ts... values, T value);


f(1); // Ts=<>
f<int, double>(1, 2, 3); // Ts=<int, double>
f<int, int>(1, 2); // error, потому что не хватает одного аргумента


Всё это приводит к забавным кейсам вроде такого

template <typename... Ts, typename... Us>
int f(Ts... ts, Us... us);


Тут Us всегда выводится из параметром (deduced), тогда как Ts должно быть указано явно. Можете попробовать понять для себя, чему они будут равны в следующих случаях:

f(1);
f(1, “2”);
f<int, char>(1, ‘2’);
f<int, char>(1, '2', “three”);


Или может быть такой угар:

template <typename... Ts, typename... Us, typename T>
int f(Ts..., Us..., T);


При любом вызове Us будет пустым паком. Что бы вы ни делали. Все компиляторы это кушают, но стандарт говорит, что если один пак всегда пустой, то это no diagnostic required (грубо говоря, нельзя так).

Ещё есть такие штуки как std::tr2::bases и std::tr2::direct_bases, которые возвращают тайплист всех базовых классов указанного и все непосредственные базовые классы указанного соответственно.

Хотя вообще доклад не об этом : ) Так что посмотрите.
  • 👍 9
More from @thisnotes
  1. Sep 17, 2026#common Сидите вы себе спокойно, разрабатываете поиск каких-нибудь объектов. Может это тов…
  2. Sep 9, 2026#cpp #books Да, книга 2001ого года. Мы ровесники. И да, в ней в основном обсуждаются какие…
  3. Sep 2, 2026#perf Попробовал собрать в кучку (кажется, немного сумбурно всё же) мысли по двум моментам…
  4. Aug 31, 2026Давайте новый тег заведём: #perf Во-первых, надо понять, что я вообще понимаю под перфом,…
  5. Aug 27, 2026#common Мы часто делаем системы, которые обладают какими-то ограничениями. Ограничения наш…
  6. Aug 24, 2026#list 0. [talk] Achieving Peak Performance for Matrix Multiplication in C++. Aliaksei Sala…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →