Skip to content

C++20 Features To Prioritize For AMReX #5375

@WeiqunZhang

Description

@WeiqunZhang

Summary

Adopt C++20 features that improve template constraints, diagnostics, and low-level utility code without fighting AMReX's GPU model or replacing existing core abstractions like Array4, GpuArray, MFIter, and particle tile views.

The best practical-now priorities are:

  • concepts / requires
  • std::span in host-side APIs only
  • <bit> utilities such as std::bit_cast, std::popcount, std::has_single_bit, std::bit_ceil
  • constinit for global/static state that must never be dynamically initialized
  • selective use of std::ranges, std::erase_if, std::ssize, and std::cmp_*
  • [[no_unique_address]] for small policy/empty-member optimization cases

Recommended Features

1. Concepts / requires

Highest-value upgrade for AMReX.

Why it fits:

  • AMReX is full of SFINAE, traits, enable_if, and callable-shape dispatch.
  • Better diagnostics matter a lot in user-facing templates and backend-specialized code.

Use first in:

  • public template entry points in particles, reductions, linear solvers, and array accessors
  • trait-heavy helpers in AMReX_TypeTraits.H
  • callable-based APIs where AMReX currently probes multiple valid forms

Guidance:

  • use named concepts for domain ideas like MultiFab-like, ParticleContainer, valid index type, callable on PTD/particle
  • keep if constexpr for real behavior branching
  • do not convert all metaprogramming helpers at once

2. std::span for host-facing contiguous views

Useful, but not as a replacement for core AMReX views.

Good targets:

  • host-only helper APIs that currently take pointer-plus-length
  • metadata and buffer utilities
  • test/helper code and non-kernel plumbing

Do not use as blanket replacements for:

  • Array4
  • GpuArray
  • particle tile/device views
  • APIs that must be obviously device-callable across CUDA/HIP/SYCL

Rule of thumb:

  • span for host-side contiguous metadata and buffers
  • existing AMReX views remain the kernel/data-path abstraction

3. <bit> utilities

Good fit for low-level numeric and systems code.

Most useful:

  • std::bit_cast
  • std::popcount
  • std::has_single_bit
  • std::bit_ceil
  • std::bit_floor
  • std::rotl / std::rotr where relevant

Good targets:

  • descriptor/packing code
  • alignment and rounding helpers
  • power-of-two checks and bucket sizing
  • integer masks and bit reinterpretation

4. constinit

Good guardrail for process-wide and backend/runtime globals.

Good targets:

  • global counters, flags, and static storage that should never rely on dynamic initialization order
  • backend/runtime globals in base infrastructure
  • diagnostic/profiler state that is trivial to initialize

Do not force it on objects that are not constant-initializable.

5. Low-risk standard library conveniences

Worth using incrementally:

  • std::ssize
  • std::cmp_less / std::cmp_greater_equal / related cmp helpers
  • std::erase_if
  • selective host-side std::ranges algorithms

Use ranges narrowly:

  • host-only leaf algorithms
  • tests and tooling
  • places where they are clearly simpler

Do not push ranges into hot kernels or template-heavy internals just for style.

6. [[no_unique_address]]

Useful for lightweight wrappers carrying empty policies, tags, allocators, or functors.

Good targets:

  • policy objects
  • allocators/tags
  • empty functors in wrappers

Treat as a local optimization tool, not a broad style shift.

Lower Priority Features

Not worth prioritizing now:

  • std::format
  • std::jthread, std::barrier, std::latch
  • coroutines
  • modules
  • blanket ranges rewrites

Use only with a concrete payoff:

  • consteval
  • abbreviated function templates
  • templated lambdas as a style migration
  • using enum

Public API Guidance

First public-facing C++20 changes should be:

  • replace enable_if-based public templates with named concepts and requires
  • add host-only overloads that accept std::span where AMReX currently takes contiguous buffers by pointer/size
  • improve constraint errors on user callables in particle, reduction, and iterator-style APIs

Do not make public APIs depend on C++20 facilities that are awkward in device code unless the API is explicitly host-only.

Validation Criteria

For any adoption:

  • compiles across CPU, CUDA, HIP, and SYCL configurations
  • does not worsen device-callable ergonomics
  • improves diagnostics or removes brittle SFINAE
  • does not replace established AMReX abstractions without a clear gain
  • stays readable to contributors who are comfortable with modern C++ but not template-metaprogramming specialists

Good trial areas:

  • convert one trait-heavy callable API to concepts
  • convert one pointer-plus-length host utility to std::span
  • replace one low-level bit helper with <bit>
  • mark a few obvious globals constinit and verify no initialization-order regressions

Prepared by Codex.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions