Да, книга 2001ого года. Мы ровесники.
И да, в ней в основном обсуждаются какие-то решения, которые сегодня уже всем знакомы и лежат в стандартной библиотеке сто лет. Но есть но...
Содержание:
1. Policy-Based Class Design.
Глава рассказывает про сложности создания качественного кастомизируемого дизайна общих классов и почему множественное наследование не помогает в решении проблемы экспоненциального роста потенциальных версий ваших компонент. Есть примеры использования различных policy.
В конце обсуждается, как декомпозировать ваш класс на policy. Есть такой совет: «Anything that can be done in more than one way should be identified and migrated from the class to a policy». Важно помнить, что книга для пишущих общего вида библиотеки. Скорее всего для общего решения в продуктовом коде правильнее будет сказать: «Выносите то, что прямо сейчас нужно вынести». Не наперёд, а в моменте.
2. Techniques.
Вторая глава рассказывает про набор отдельных утилиток и возможностей языка, которые могут применяться в более общих решениях. Некоторые из них:
- compile-time assertions (до
static_assert)- partial template specialization
- integral constant to type (дед
std::integer_constant)- type-to-type mapping
- type selection (
std::conditional)- TypeTraits (правда тут это класс с константами, а не как у нас «вчера» шаблонные структуры)
3. Typelists.
Typelists конечно не поддерживают произвольное количество аргументов (потому что шаблоны не умели). Выглядят они так:
typelist<type1, typelist<type2, type3>>
Дальше реализовываются разные операции и рассказывается про применение класса.
4. Рассказывает про проблемы стандартного аллокатора и после введения локальных понятий поясняет реализацию small-object аллокатора.
5. Про паттерн Command и generalized functor для его реализации. Фактически
std::function. 6. Рассказывает про реализацию Singleton.
Причём довольно подробно описывая проблемы разных подходов. В итоге приходим к Meyers singleton. После небольшого chatgpt-like фактчека оказалось, что именно в этой книге Andrei Alexandrescu подарил миру это название.
Далее он рассматривает самоназванную KDL problem (которая легко может возникнуть на практике) и изобретает Phoenix singleton для её решения.
К концу главы обсуждается реализация singletone для многопоточного случая и общая policy-based реализация.
7. Про умные указатели.
Кто такие, как пользоваться и как должны быть реализованы с точки зрения различных случаев на практике.
8 и 9. Про фабрики и абстрактные фабрики.
10. Посвящена паттерну visitor.
11. Реализации мультиметодов.
Это как бы перегрузка функций, которая знает чуть больше, чем положена. Кратко можно пояснить так:
class Shape {};
class Asteroid : public Shape {};
class Spaceship : public Shape {};
void Collide(Asteroid& a, Spaceship& s) { /* Logic 1 */ }
void Collide(Shape& s1, Shape& s2) { /* Logic 2 */ }
И вот обычно вы бы вызвали
Collide на основании того, какая ссылка была передана. Если Asteroid был передан как Shape, то вызовется общая функция для Shape. Вот мультиметоды позволяют понять, какой объект на самом деле лежит в памяти и вызвать для него соответствующую перегрузку. Каждая глава проходит путь от каких-то простых реализаций до более продвинутых через рассмотрение ошибок и проблем, которые возникают при неаккуратном дизайне.
Сегодня конечно книга выглядит уже скорее как исторический артефакт. Но!
• первая глава про policy-based design всё ещё актуально, потому что говорит концептуальные вещи. Мне она сильно запомнилась и помогла на некоторые концепции иначе смотреть.
• большинство других глав полезны с точки зрения понимания, как стоит смотреть на проектирование общих решений.
То есть если не воспринимать книгу как справочник по C++, а попытаться увидеть в ней мануал по проектированию на примере конкретных задач, получится очень даже полезно.
@thisnotes. Patreon, newsletter.
Спасибо Artyom Garkavy и niki4smirn.

