Skip to content
alexandrescu-modern-cpp-design logo

Andrei Alexandrescu Style Guide

alexandrescu-modern-cpp-design

Write C++ code following Andrei Alexandrescu's Modern C++ Design principles. Emphasizes policy-based design, template metaprogramming, and type-safe generic abstractions. Use when designing flexible, reusable libraries or when compile-time computation beats runtime overhead.

SKILL.md

Full skill instructions

Andrei Alexandrescu Style Guide

Overview

Andrei Alexandrescu's "Modern C++ Design" revolutionized how we think about C++ templates. His work on Loki library and policy-based design showed that templates are not just for containers—they're a compile-time programming language.

Core Philosophy

"C++ templates are Turing-complete. Use this power wisely."

"Policy-based design: assemble types from interchangeable parts."

Alexandrescu believes in pushing computation to compile time and using the type system as a design tool, not just a safety mechanism.

Design Principles

  1. Policy-Based Design: Build classes from interchangeable policy classes that customize behavior without inheritance overhead.

  2. Compile-Time over Runtime: What can be computed at compile time should be.

  3. Type Lists and Metaprogramming: Types themselves become first-class citizens that can be manipulated.

  4. Design Patterns in Types: Classic GoF patterns implemented with zero runtime overhead.

When Writing Code

Always

  • Consider if behavior can be a compile-time policy
  • Use static_assert to document and enforce requirements
  • Prefer tag dispatching over runtime branching for type-based logic
  • Make templates SFINAE-friendly (C++11/​14) or use concepts (C++20)
  • Document template requirements explicitly

Never

  • Use runtime polymorphism when static polymorphism suffices
  • Write duplicate code that differs only in types
  • Ignore compile-time computation opportunities
  • Leave template errors to become cryptic instantiation failures

Prefer

  • Policy classes over strategy pattern (no vtable)
  • Type traits over runtime type checking
  • constexpr functions over template metafunctions (modern C++)
  • Concepts over SFINAE (C++20)
  • Variadic templates over recursive type lists (modern C++)

Code Patterns

Policy-Based Design

// Traditional OOP: Runtime overhead, fixed at compile time anyway
class Widget : public ICreationPolicy, public IThreadingPolicy { /​* ... */ };

// Policy-Based: Zero overhead, infinitely configurable
template <
    class CreationPolicy,
    class ThreadingPolicy = SingleThreaded,
    class CheckingPolicy = NoChecking
>
class SmartPtr : public CreationPolicy, 
                 public ThreadingPolicy,
                 public CheckingPolicy {
    // Policies are mixed in, no vtable
};

// Usage: Configure at compile time
using ThreadSafePtr = SmartPtr<HeapCreation, MultiThreaded, AssertCheck>;
using FastPtr = SmartPtr<HeapCreation, SingleThreaded, NoChecking>;

// Policies are just classes with required interface
struct HeapCreation {
    template<class T>
    static T* Create() { return new T; }
    
    template<class T>
    static void Destroy(T* p) { delete p; }
};

struct SingleThreaded {
    struct Lock {
        Lock() = default;  // No-op
    };
};

struct MultiThreaded {
    struct Lock {
        Lock() { /​* acquire mutex */ }
        ~Lock() { /​* release mutex */ }
    };
};

Type Traits and SFINAE

// Type trait: Does T have a serialize() method?
template<typename T, typename = void>
struct has_serialize : std::false_type {};

template<typename T>
struct has_serialize<T, 
    std::void_t<decltype(std::declval<T>().serialize())>
> : std::true_type {};

// Use it for conditional behavior
template<typename T>
auto save(const T& obj) -> std::enable_if_t<has_serialize<T>::value> {
    obj.serialize();
}

template<typename T>
auto save(const T& obj) -> std::enable_if_t<!has_serialize<T>::value> {
    default_serialize(obj);
}

// C++20: Much cleaner with concepts
template<typename T>
concept Serializable = requires(T t) {
    { t.serialize() } -> std::convertible_to<std::string>;
};

void save(Serializable auto const& obj) {
    obj.serialize();
}

Compile-Time Type Lists (Classic Alexandrescu)

// Type list: A compile-time list of types
template<typename... Ts>
struct TypeList {};

// Operations on type lists
template<typename List>
struct Length;

template<typename... Ts>
struct Length<TypeList<Ts...>> {
    static constexpr size_t value = sizeof...(Ts);
};

// Get type at index
template<size_t I, typename List>
struct TypeAt;

template<typename Head, typename... Tail>
struct TypeAt<0, TypeList<Head, Tail...>> {
    using type = Head;
};

template<size_t I, typename Head, typename... Tail>
struct TypeAt<I, TypeList<Head, Tail...>> {
    using type = typename TypeAt<I - 1, TypeList<Tail...>>::type;
};

// Usage
using MyTypes = TypeList<int, double, std::string>;
static_assert(Length<MyTypes>::value == 3);
using Second = TypeAt<1, MyTypes>::type;  // double

Visitor Pattern via Templates

// Traditional visitor: Virtual dispatch at every node
// Alexandrescu approach: Static visitor with type list

template<typename... Types>
class Variant;

template<typename Visitor, typename Variant>
auto visit(Visitor&& v, Variant&& var) {
    return var.visit(std::forward<Visitor>(v));
}

// Modern C++ (std::variant does this)
using Value = std::variant<int, double, std::string>;

auto result = std::visit(overloaded{
    [](int i) { return std::to_string(i); },
    [](double d) { return std::to_string(d); },
    [](const std::string& s) { return s; }
}, value);

// The 'overloaded' helper (Alexandrescu-style)
template<class... Ts> 
struct overloaded : Ts... { 
    using Ts::operator()...; 
};
template<class... Ts> 
overloaded(Ts...) -> overloaded<Ts...>;

Mental Model

Alexandrescu thinks of C++ templates as a compile-time functional language:

  1. Types as values: Types can be computed, stored, and transformed
  2. Templates as functions: Template instantiation is function application
  3. Specialization as pattern matching: Like case statements on types
  4. Recursion for iteration: Compile-time loops via recursive templates

The D Language Connection

Alexandrescu later co-designed D, which incorporates many C++ template lessons:

  • Built-in compile-time function execution
  • String mixins for code generation
  • Better error messages for templates

These ideas now appear in modern C++ (constexpr, if constexpr, concepts).

When to Apply

Use Alexandrescu's techniques when:

  • You need maximum performance (zero runtime overhead)
  • Behavior variations are known at compile time
  • You're building a library with many configuration options
  • Type-based dispatch is frequent

Avoid when:

  • Runtime polymorphism is genuinely needed
  • Compile times are already problematic
  • Team isn't comfortable with template metaprogramming

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View