|
| 1 | +# Common CCCL Style Guidance |
| 2 | + |
| 3 | +Apply this guidance across CCCL unless a path-specific style reference says otherwise. |
| 4 | + |
| 5 | +## Naming Style |
| 6 | + |
| 7 | +- Macros: macro style, e.g. `MY_MACRO`. |
| 8 | +- Template parameters: PascalCase, e.g. `MyParameter`. |
| 9 | +- All other symbols: snake style, e.g. `my_variable`. The one exception is the CUB public API, which uses PascalCase. |
| 10 | + |
| 11 | +## Variables |
| 12 | + |
| 13 | +- All variables that are not modified must use `const`. This includes variables initialized by casts (`static_cast`, `reinterpret_cast`, `bit_cast`), function return values, and loop-invariant computations. |
| 14 | +- All variables that can be evaluated at compile-time must use `constexpr`. |
| 15 | +- All `constexpr` variables at namespace/global scope must use `inline`, including variable templates. |
| 16 | +- Consider using plural names for array, span, list, e.g. `int values[4]` instead of `int value[4]`. |
| 17 | +- Use uniform initialization for class constructors (not enforced to builtin types) and compile-time conversions, e.g. `constexpr auto x = int{sizeof(float)};`. |
| 18 | + |
| 19 | +## Headers |
| 20 | + |
| 21 | +- Files must include all headers related to the symbols that they are using. |
| 22 | +- Relying on transitive header inclusion is not allowed. |
| 23 | +- Unneeded headers must be removed. |
| 24 | +- All headers must have the correct license. This also applies to source files. |
| 25 | +- All header inclusions must use the syntax `<header>`. |
| 26 | +- Use forward declaration, namely `__fwd/header.h` or direct type declaration, when possible instead of including the implementation header. |
| 27 | +- Headers should be the most precise available, e.g. `#include <cuda/std/__type_traits/is_array.h>`. |
| 28 | +- Do not include headers in `cuda/std/__cccl/` directly; they are provided by `__config` or the prologue/epilogue mechanism. |
| 29 | + |
| 30 | +## Functions |
| 31 | + |
| 32 | +- Functions must be marked `_CCCL_HOST_API`, `_CCCL_DEVICE_API`, `_CCCL_HOST_DEVICE_API`, `_CCCL_TILE_API`, or `_CCCL_API`. |
| 33 | +- Non-template, non-`constexpr` functions must use `inline`. |
| 34 | +- Most functions with a non-void return type should use `[[nodiscard]]`; functions with known side effects may be exceptions. |
| 35 | +- Functions that do not throw exceptions must use `noexcept`. |
| 36 | +- Use `_CCCL_CONSTEVAL` when the function can only be evaluated at compile time. |
| 37 | +- Use C++20 concept macros instead of SFINAE, e.g. `_CCCL_TEMPLATE(...)` and `_CCCL_REQUIRES(...)`. |
| 38 | + |
| 39 | +## Function Calls And Types |
| 40 | + |
| 41 | +- In headers, apply global qualification where the subproject requires it: |
| 42 | + - libcudacxx and cudax require free function calls to be fully qualified from the global namespace, e.g. `::cuda::ceil_div(...)`. |
| 43 | + - CUB applies this rule only to calls to symbols under the `::cuda` namespace hierarchy; otherwise follow existing CUB qualification style. |
| 44 | + - Thrust uses leading `::` for many symbols under the `::cuda` namespace hierarchy, but relies on ADL in many places and the blanket free-function qualification rule does not apply to those calls. |
| 45 | +- For covered calls, this includes calls to functions defined in the same namespace, e.g. inside `cuda::`, call `::cuda::ceil_div(...)`, not `ceil_div(...)`. This does not apply to (static) member functions of classes. The only exceptions for covered calls are functions that are supposed to be found through argument-dependent lookup (ADL), such as `::cuda::std::swap` and `::cuda::std::get`. Those functions can be called unqualified with a preceding `using ::cuda::std::get;`. |
| 46 | +- This global-qualification rule does not apply to source files such as tests and benchmarks. |
| 47 | +- In headers, apply type-name qualification where the subproject requires it: |
| 48 | + - libcudacxx and cudax require type names to be fully qualified except when they are already declared in the current namespace or an enclosing one. Outside those namespaces, fully qualify `cuda::std` and standard integer type aliases such as `::cuda::std::size_t`. |
| 49 | + - CUB applies this rule only to type names under the `::cuda` namespace hierarchy. Do not apply the libcudacxx/cudax blanket type-qualification rule to CUB namespaces or `detail` namespaces. |
| 50 | + - Thrust does not apply the libcudacxx/cudax blanket type-qualification rule. It uses leading `::` for many `::cuda` and `::cuda::std` type names, but also uses Thrust namespace patterns; follow neighboring Thrust code. |
| 51 | +- A local `using` declaration, e.g. `using ::cuda::std::size_t;`, is acceptable to avoid repetition within a function body. |
| 52 | +- Static member functions of a class template inherit the class's namespace. |
| 53 | + |
| 54 | +## Comments |
| 55 | + |
| 56 | +- Commented code without a description is not allowed. |
| 57 | + |
| 58 | +## General Guidelines |
| 59 | + |
| 60 | +- The code must reuse `cuda/` or `cuda/std` functionalities as much as possible, including macros. |
| 61 | +- Try to use modern C++ as much as possible. The repository supports C++17 but many more recent functionalities have been backported with functions and macros. |
| 62 | + |
| 63 | +## Prevent Compiler Errors And Improve Compatibility |
| 64 | + |
| 65 | +- Remove unused code, variables, functions, types, template parameters, headers, etc. |
| 66 | +- Variables that are unsigned, or that can become unsigned after template instantiation, must not check for negative values directly. Use `cuda::std::is_unsigned_v<T> ? false : (var < 0)` instead. |
| 67 | + |
| 68 | +## Compiler Compatibility |
| 69 | + |
| 70 | +- Protect host-only code with `#if !_CCCL_COMPILER(NVRTC)`. |
0 commit comments