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.
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/requiresstd::spanin host-side APIs only<bit>utilities such asstd::bit_cast,std::popcount,std::has_single_bit,std::bit_ceilconstinitfor global/static state that must never be dynamically initializedstd::ranges,std::erase_if,std::ssize, andstd::cmp_*[[no_unique_address]]for small policy/empty-member optimization casesRecommended Features
1. Concepts / requires
Highest-value upgrade for AMReX.
Why it fits:
enable_if, and callable-shape dispatch.Use first in:
AMReX_TypeTraits.HGuidance:
if constexprfor real behavior branching2.
std::spanfor host-facing contiguous viewsUseful, but not as a replacement for core AMReX views.
Good targets:
Do not use as blanket replacements for:
Array4GpuArrayRule of thumb:
spanfor host-side contiguous metadata and buffers3.
<bit>utilitiesGood fit for low-level numeric and systems code.
Most useful:
std::bit_caststd::popcountstd::has_single_bitstd::bit_ceilstd::bit_floorstd::rotl/std::rotrwhere relevantGood targets:
4.
constinitGood guardrail for process-wide and backend/runtime globals.
Good targets:
Do not force it on objects that are not constant-initializable.
5. Low-risk standard library conveniences
Worth using incrementally:
std::ssizestd::cmp_less/std::cmp_greater_equal/ related cmp helpersstd::erase_ifstd::rangesalgorithmsUse ranges narrowly:
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:
Treat as a local optimization tool, not a broad style shift.
Lower Priority Features
Not worth prioritizing now:
std::formatstd::jthread,std::barrier,std::latchUse only with a concrete payoff:
constevalusing enumPublic API Guidance
First public-facing C++20 changes should be:
enable_if-based public templates with named concepts andrequiresstd::spanwhere AMReX currently takes contiguous buffers by pointer/sizeDo 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:
Good trial areas:
std::span<bit>constinitand verify no initialization-order regressionsPrepared by Codex.