# Qzhong Cpp Style

> Write, refactor, or review C++ and CUDA C++ in QZhong's personal style, inferred from BSplineInterpolation, mct/libmeq, clap.h, and the cuMES coding guide. Use for C++ implementation in QZhong's projects or requests to code like QZhong; preserve the target project's compatibility and local conventions.

- Skill: `12ff54e/qzhong-cpp-style` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add 12ff54e/qzhong-cpp-style`
- Raw SKILL.md: https://api.skillmd.com/api/skills/12ff54e/qzhong-cpp-style/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: 12ff54e (https://skillmd.com/u/12ff54e)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/12ff54e/qzhong-cpp-style

---


# QZhong C++ Style

Write compact, mathematically legible C++ with reusable typed components,
convenient public APIs, and explicit control over storage and computation.
Put flexibility in types and overloads while keeping the numerical algorithm
visible as ordinary expressions and loops.

## Resolve the context first

Read the target's applicable instructions, language standard, formatter, and a
nearby interface and implementation. Follow explicit task/repository rules
first, then the conventions of the code being edited, then these defaults.
Use cuMES's explicit naming and ownership rules as defaults for new code.
Do not rename established APIs or modernize an entire file just to match them.

BSplineInterpolation supports C++11; cuMES requires strict C++20. Use the
target's standard. On C++20 targets, express new constraints with
concepts/requires or simple traits when appropriate; preserve SFINAE and
compatibility guards in older libraries. Do not add polyfills to modern targets
merely because the source projects contain them.

For evidence, exceptions, or an explanation of the user's style, read
[references/style-evidence.md](references/style-evidence.md). Ordinary use does
not require reopening the original projects.

## Names and surface form

- Use `PascalCase` for types, `snake_case` for functions and variables, and
  `CAPITAL_SNAKE_CASE` for constants and scoped-enum enumerators in new APIs.
  Keep established mathematical/physics names such as `psi`, `dpdr`, `rmnc`,
  `ns`, `nZnT`, and `jF`. Do not expand clear formulas into verbose prose names.
- Put `using val_type = T;` first in the public section of scalar-templated
  classes/structs. Give other roles descriptive aliases such as `coord_type`,
  `size_type`, `matrix_type`, and `error_type`. Derive aliases from component
  types rather than repeating concrete types. Do not invent a scalar alias
  for a template with no scalar role, such as `CLAP<Config>`.
- Prefer trailing underscores for private data in new classes. Private helper
  suffixes such as `build_solver_` occur frequently; follow neighboring code
  rather than requiring a suffix for every private function. Plain data structs
  can expose named fields directly.
- Use the existing `.clang-format`. The shared baseline is Chromium, four-space
  indentation, 80 columns, attached braces, and short if/loop/block bodies
  allowed on one line. Small accessors like `size() const { return size_; }`
  and guards like `if (empty()) { return; }` fit the style.
- Wrap long templates, signatures, initializer lists, and formulas with the
  formatter's continuation alignment. Keep `T*`/`T&` spelling and include
  grouping consistent with the target. Include order differs between the old
  libraries and cuMES; there is no universal personal include order.
- For a new project without a formatter, use
  [assets/clang-format](assets/clang-format) as a `.clang-format` starting point.
  Do not replace an existing configuration or reformat unrelated code.

## Types, APIs, and decomposition

- Parameterize genuinely variable scalar types, dimensions, orders, and
  callable policies. Use fixed-size `std::array` when the shape is known at
  compile time. Keep one source of truth for precision and derive downstream
  types from it; distinct coordinate/value/accumulation types can be intentional.
- Prefer concrete composition, function templates, and callable parameters for
  numerical customization. Small lambdas should express the user's field
  formula at the call site. Use traits to derive output shape when useful.
  CRTP fits a shared implementation with real static specializations; it is
  an available technique, not a requirement for every class.
- Provide a clear core operation and a few useful convenience forms. Delegate
  constructors/overloads to one implementation. Examples are coordinate-array
  plus variadic overloads, `operator()` for a mathematical callable, and `solve`
  backed by `solve_in_place`.
- Where both access modes are useful, distinguish ordinary evaluation from an
  explicitly checked form such as `at`/`derivative_at`. Document preconditions;
  do not add duplicate checks to every layer of a numerical hot path.
- Keep configuration, raw input, reusable computation, and output representation
  distinguishable. Use small structs for coherent values and owning classes
  for reusable state. Avoid introducing interface hierarchies, factories, or
  extra modules without a concrete variation or ownership need.
- Header-only template libraries and small single-header utilities are natural
  here. Keep non-template implementation in source files when that is the
  target's pattern. Do not force cuMES's explicit-instantiation layout onto a
  standalone CPU library.

## Ownership and cost

- Use values and RAII ownership. Prefer `std::vector`/`std::array` for storage,
  references for objects, and `std::span`/`std::string_view` for borrowed data
  when the language standard permits. In new host APIs, use
  `std::optional<std::reference_wrapper<T>>` for a nullable borrowed object
  where appropriate. Preserve iterator-range APIs in compatible libraries.
- Keep raw pointers at necessary interop/device boundaries. In CUDA code use
  the project's buffer/arena owners and typed views; retain `d_`/`h_` pointer
  prefixes where applicable. Old pointer arithmetic in clap.h is not a model
  for new ownership or reflection code.
- Separate expensive setup from repeated work when reuse exists: build/factor
  once, solve/evaluate many times; cache coordinate-dependent work separately
  from changing field values. Reserve known capacities and reuse scratch where
  it matters. Do not add a cache or allocator without a demonstrated use.
- Pass read-only containers by const reference or view. Move owned storage into
  an object; use forwarding references only when forwarding serves the API.
  Return local values normally to allow copy elision. Preserve meaningful
  `const&`/`&&` overloads for reuse versus consumption.
- Keep memory layout and loop order explicit. Flat contiguous storage and
  dimensional wrappers recur, but BSpline Mesh is row-major and cuMES uses
  column-major layouts: honor the algorithm's actual contract.

## Numerical implementation and diagnostics

- Write recognizable formulas and direct loops. Use short local lambdas for
  nearby transformations, `auto` for obvious or complicated derived types,
  and explicit scalar/index types when precision or signedness matters.
  Prefer named intermediates when a conditional or expression becomes hard to
  read; compact code need not become a dense nested ternary.
- Use `const`, `constexpr`, explicit conversions, and typed zero initialization
  where their meaning is useful. Keep precision conversions deliberate; do not
  change accumulation type or floating-point evaluation order as a style edit.
- Use compile-time checks for type/shape constraints, runtime validation for
  external input, and assertions for internal invariants, following the target's
  error mechanism. Diagnostics should identify the offending value/option and
  the expected condition. Do not copy old unchecked parsing behavior.
- Macros are acceptable for an existing registration DSL, configuration switch,
  or compatibility boundary. The preference shown by clap.h is concise typed
  registration at the call site; macros and byte offsets are not universal
  implementation requirements.
- Comment mathematical meaning, units, ordering, boundary/periodicity
  conventions, and non-obvious lifetime or performance decisions. Short section
  comments can mark algorithm stages. Use concise Doxygen documentation for
  public templates when neighboring code does, without narrating every statement.

## Verification

Use the project's checks. For numerical changes, favor observable mathematical
properties, analytic cases, residuals, or CPU-reference comparisons, including
relevant precision and boundary cases. The source projects favor standalone
test executables with lightweight assertions; do not introduce a test framework
just for a small addition. Keep correctness checks separate from timing claims.

In cuMES, consult its current verification rules before a numerical refactor:
the frozen trajectory and controller decisions can be part of correctness.
Those gates, GPU-only execution, and allocation-at-startup requirements are
project contracts, not universal C++ preferences.

