C++ guidelines¶
Prefer private (or static) functions over anonymous scopes
{ ... }.Use
//comments, not/* */. Exception:/* */is a good choice for inline argument-name annotations at a call site, e.g.f(/*count=*/3, /*noisy=*/true).Use
longfor sizes and indices, notintorsize_tUse spaces, not tabs.
Functions which take an
ostream &argument should not modify stream state in the caller.If a class
Xderives fromstd::enable_shared_from_this, then its constructor(s) must be protected, and the class must definecreate()static method(s) that returnshared_ptr<X>.Minimize header
#includedependencies. In a.hpp, if a type is only used by pointer, reference, orstd::shared_ptr<T>(not by value, as a base class, or via member access /sizeof), forward-declare it instead of#include-ing its header, and move the#includeinto the.cppfile(s) that use the full type. This cuts recompilation when the included header changes. Match the declared keyword (classvsstruct) and note where it lives, e.g.:class SlabAllocator; // defined in SlabAllocator.hpp struct XEngineMetadata; // defined in XEngineMetadata.hpp
Caveat: keep the full
#includein the header when the complete type is needed there – a base class, a by-value member, an inline function that touches the type, or astd::unique_ptr<T>member of a class whose destructor is compiler-generated in the header (unique_ptrneeds a complete type at the destructor;shared_ptrdoes not). When unsure, include it.
ksgpu¶
Uses the ksgpu helper library, especially the Array class (ksgpu/Array.hpp), memory managment (ksgpu/mem_utils.hpp),
and xassert macros (ksgpu/xassert.hpp, see below).
CRITICAL: please complain if you don’t see the ksgpu library in the cursor/claude workspace.
xassert macros¶
The following macros are similar to assert(), but throw an exception instead of terminating:
xassert(cond); // throw exception unless bool(cond)==true
xassert_eq(x,y); // throw exception unless x==y
xassert_divisible(x,y); // throw exception unless (x % y) == 0
// also: xassert_ne(), xassert_lt(), xassert_le(), xassert_gt(), xassert_ge()
// Throw exception unless 'arr' (type ksgpu::Array) has shape {3,4,5}.
// IMPORTANT: note parentheses around the shape -- these are needed to compile!
xassert_shape_eq(arr, ({3,4,5}));
The exception text shows the file/line (like regular assert()), plus values of the arguments x and y.
In the case of xassert_shape_eq(), both array shapes are shown.
Please use xassert() for argument-checking and error-checking, unless there is a reason to create a more verbose error message.
For example:
void f(int x, int y, int z)
{
// Example 1: you should replace this by xassert_eq(x,y), since the xassert_eq() error message
// contains the same information as the message below (namely, numerical values of x and y).
if (x != y) {
stringstream ss;
ss << "f(): expected x==y, got x=" << x << ", y=" << y;
throw runtime_error(ss.str());
}
// Example 2: you should not replace this by xassert_lt(x+y,z), since the xassert_lt() error message
// contains less information than the message below (which shows x,y,z individually)
if ((x+y) >= z) {
stringstream ss;
ss << "f(): expected (x+y) < z, got x=" << x << ", y=" << y << ", z=" << z;
throw runtime_error(ss.str());
}
// Example 3: you should replace this by xassert_shape_eq(arr, ({M,N})), since the xassert_shape_eq()
// message contains more information (namely, the actual and expected array shapes).
if ((arr.ndim != 2) || (arr.shape[0] != x) || (arr.shape[1] != y)) {
stringstream ss;
ss << "f(): expected shape (x,y) = (" << x << "," << y << "), got " << arr.shape_str();
throw runtime_error(ss.str());
}
}