This convention applies to the ark reorganization and subsequent development. Public interfaces, implementation names and filenames consistently use snake_case.
CMake requires C++20 and propagates it through the core and configuration targets. The maintained runtime uses these conventions:
| Area | Implementation | Compatibility |
|---|---|---|
| Template selection | Concepts, standard type utilities and if constexpr |
Existing exact-type traits and public aliases remain valid |
| Receiver callbacks | std::bind_front |
Receivers remain borrowed; parameter references, return values and priorities stay unchanged |
| Logging | std::source_location, __VA_OPT__ |
Existing logging call forms remain valid |
| Binary helpers | std::endian, fixed-extent std::span |
Existing hash migration functions and XXTEA ciphertext remain unchanged |
| Resource owners | RAII, explicit copy/move rules | See compression ownership and container contracts |
| Database tasks | Asio awaitables on the owner-driven runtime | See task execution |
Retain std::bind in the generic scheduler: it evaluates nested bind expressions and unwraps reference arguments. bind_front would change those supported behaviors. Platform/export macros, allocation override hooks and existing node metadata/vtable declarations also remain where replacement would change ABI or ownership. Vendored sources retain upstream conventions; PhysX 3 and simulation are still unsupported integrations.
This scope does not implement the separately deferred Registry, hot update, nested synchronization wire format, complete teardown ordering or deployment-capacity acceptance.
| Item | Convention | Examples |
|---|---|---|
| Namespaces | Lowercase words separated by underscores | ark, ark::detail |
| Classes, structs and type aliases | snake_case |
plugin_manager, module, data_list |
| Enumeration types and values | snake_case |
data_type::dt_int64 |
| Functions and methods | snake_case |
find_module(), start(), stop() |
| Local variables and parameters | snake_case |
module_name, initial_buffer_size |
| Private and protected members | snake_case with a trailing underscore |
module_name_, state_ |
| Public struct fields | snake_case |
session_id |
| Compile-time constants | snake_case |
default_buffer_size |
| Template parameters | snake_case |
module_type, buffer_size |
| Preprocessor macros | UPPER_SNAKE_CASE, prefixed with ARK_ |
ARK_EXPORT |
| C++ filenames | snake_case; .hpp headers and .cpp implementations |
plugin_manager.hpp, plugin_manager.cpp |
The public type form after migration is ark::plugin_manager. Name interfaces and implementations by responsibility; new interfaces do not use AFI or AFC type prefixes. Preserve identifiers belonging to dependencies.
- Use four spaces, no tabs, and a 120-column limit.
- Group includes in this order: system libraries, third-party libraries, project headers. Separate groups with a blank line.
- Place a function's opening brace on the signature line. Expand short functions, including empty bodies.
- Use braces for conditional and loop bodies, including short branches.
- Leave blank lines between includes and code, namespaces and their definitions, and adjacent type or function definitions.
clang-formathandles formatting. Interface review and applicable static checks enforce naming.
This example illustrates naming and formatting:
#include <cstddef>
namespace ark {
class session_counter
{
public:
void add(std::size_t count) {
count_ += count;
}
std::size_t count() const {
return count_;
}
private:
std::size_t count_ = 0;
};
} // namespace arkARK_FORMAT and ARK_FORMAT_FUNCTION use standard C++20 __VA_OPT__ for zero
or multiple formatting arguments, including dynamic format strings. They retain
fmt::runtime formatting and literal-brace handling. ARK_FORMAT remains an
expression; ARK_FORMAT_FUNCTION retains its [function:line] caller prefix
and historical trailing statement terminator. Existing call forms are unchanged.
ARK_LOG_TRACE, ARK_LOG_DEBUG, ARK_LOG_INFO, ARK_LOG_WARN, ARK_LOG_ERROR
and ARK_LOG_CRITICAL retain their format/argument call forms and log levels.
They use C++20 std::source_location at the macro caller and __VA_OPT__ for
optional formatting arguments. Output keeps the [basename:line] prefix;
basename extraction recognizes both / and \, and the source function name
remains empty. Formatting, argument evaluation, message ownership and logger
configuration/lifecycle are unchanged.
MSVC needs its standard-conforming preprocessor (/Zc:preprocessor) for
__VA_OPT__. The public ark::core target propagates this option to consumers.
When compiling ark headers without that target, enable this option together with
C++20 mode.
Source compatibility note: ark no longer defines the implementation helpers
SPDLOG_STRRCHR and SPDLOG_FILE_BASENAME. Existing externally supplied macros
are left defined, but a custom SPDLOG_FILE_BASENAME no longer changes
ARK_LOG_* filenames. Code using those old helper definitions must provide its
own basename operation; use std::string_view::find_last_of("/\\") when both
separator kinds are needed. This does not require changing ordinary ARK_LOG_*
call sites.
- Use C++20 and target-scoped dependencies. Public headers explicitly include the standard-library headers they need.
- Manage resources through RAII and explicit ownership. Document the lifetime of borrowed pointers, references and views.
- Use
override,finalandconstto express interface constraints. - Write English comments describing constraints, reasoning and non-obvious behavior. Document public API lifetime, threading and error contracts.
- Review formatting separately from behavior changes. Migrate a module together with its consumers, examples and tests.
Use clang-format 18 and the checked-in configuration:
./scripts/format.sh
./scripts/format.sh --checkFor semantic naming checks, configure a compilation database before running clang-tidy (the existing validation uses version 22):
cmake -S . -B style-build -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build style-build
./scripts/clang_tidy.sh style-build
./scripts/clang_tidy.sh style-build src/application/main.cppThe default clang-tidy invocation checks source files present in that build's
compilation database; enable optional plugins to check their translation units.
Plugin entry symbols DllEntryPlugin and DllExitPlugin retain their required
spelling alongside third-party APIs and reflected strings.
The clang-tidy command needs the configured build's compilation database and a compatible compiler toolchain. Set CLANG_FORMAT or CLANG_TIDY when selecting a nondefault executable. Formatting covers tracked and new ark-owned C++ and Protobuf sources; vendored implementations and generated build outputs retain their own rules.
Protocol definitions use snake_case and the ark::protobuf C++ namespace, with consul and osslog retaining their existing packages. The generator's .pb.h suffix remains unchanged. Configuration keys, reflection strings, external JSON names and the C# generator's business-facing names keep their required spelling. See Protobuf messages for binary and source compatibility boundaries.
Edit .proto sources and regenerate their C++ output through CMake. Generated
headers use paths such as <ark/proto/common_messages.pb.h>. The naming migration
preserves message field numbers, field types, cardinality, enum numeric values
and external JSON field names. Generated C++ names, descriptor names, Any type
URLs and JSON enum strings change; rebuild consumers and update code depending
on those names. tests/core/protobuf_messages.cpp retains golden-byte regressions
for binary payload compatibility.
The configuration generator follows the same C++ naming convention and formats
meta_define.hpp before copying it into src/core/. Configuration data,
reflection strings and C# output retain their existing names.
Breaking source change: ark no longer defines ARK_CPP11_OR_GREATER,
ARK_CPP14_OR_GREATER, ARK_CPP17_OR_GREATER, ARK_NOEXCEPT, ARK_CONSTEXPR,
ARK_FINAL or MAKE_BUILDIN_TYPE. The required language version remains C++20.
| Removed name | Migration |
|---|---|
ARK_CPP11_OR_GREATER, ARK_CPP14_OR_GREATER, ARK_CPP17_OR_GREATER |
Remove obsolete guards in ark consumers; use application-owned feature checks if supporting other language standards independently. |
ARK_NOEXCEPT |
Write noexcept directly. |
ARK_CONSTEXPR |
Write constexpr directly. |
ARK_FINAL |
Write final directly. |
MAKE_BUILDIN_TYPE(T) |
Keep any intended custom classification through an explicit ark::is_buildin_type<T> specialization declaring the existing yes and no enum values. |
The C++11 std::make_unique fallback is removed; include <memory> and use the
standard C++20 library. Platform export, assertion and ownership macros keep their
existing behavior.
is_buildin_type still recognizes exactly uint16_t, uint32_t, uint64_t,
int16_t, int32_t and int64_t, including native type aliases of those types.
It does not recognize all integral types or remove cv/reference qualifiers.
Its yes/no enum values and check_buildin_type signature, exception contract
and argument deduction remain unchanged: a const integer lvalue can deduce the
unqualified type through const T&, while explicitly checking a const-qualified
trait remains false. Constant types and values, including UID bit allocation and
network timeouts, remain unchanged.
object_map and object_hashmap own their raw-pointer entries. Successful
insertion transfers ownership; duplicate or throwing insertion leaves ownership
with the caller. Each nonnull pointer needs one owning entry. The shared variants retain
shared_ptr ownership, and removing an entry does not destroy an externally owned
value. Other mapped types retain their normal destruction semantics;
std::reference_wrapper<T> remains borrowed.
clear() and destruction visit entries by reference, without copying keys or
mapped values. Cleanup therefore cannot fail from a key-copy allocation or leave
an already deleted pointer behind after a partial copied traversal. Public
signatures and class fields are unchanged; rebuild header consumers for this fix.
array_map and pointer-valued lru_map retain their borrowed-pointee semantics.
check-object-map-cleanup, included in check-core, checks ordered/hash maps,
keys that reject copying, exact raw-pointer destruction and shared/borrowed values.
<ark/string_pod.hpp> is supplied by ark::core. pod_string_iterator::operator++(int) returns the prior iterator by value; prefix ++it still returns the advanced iterator by reference. Store the old position with auto previous = it++;, rather than binding a non-const lvalue reference. A saved iterator borrows its node; it does not copy the mapped value.
Breaking source change; rebuild affected consumers and plugins: update reference bindings or explicit function signatures that relied on the old postfix reference. Emitted template instantiations can use a different calling convention despite unchanged class fields; unchanged layout does not establish binary compatibility.
get_data() retains its declared mapped_type* return type and returns the address of the stored mapped value: std::size_t* for a scalar, or T** for a pointer mapping. Assigning through that address changes the stored value/pointer slot without transferring pointee ownership. The named pod_string::get_data(key, out) lookup is unchanged.
Check it != values.end() before incrementing or calling get_key() / get_data(). Empty ranges have begin() == end(); do not dereference or increment end. Advancing one iterator does not change a saved prior position, but removing its node, clearing or destroying its container ends that borrowed lifetime. The custom iterator and const-iteration APIs are otherwise unchanged. Core header checks instantiate scalar and pointer mappings; check-core covers saved postfix values, storage mutation, empty/end comparisons and the existing array_map lookup path.
<ark/container/lru_map.hpp> stores values, recency keys and internal links as one
cache. Copies retain capacity and recency order, rebuild links into their own key
list, and remain usable after the source changes or is destroyed. Mapped values
retain their normal copy semantics, including shared ownership for shared_ptr.
Copying prepares empty container bookkeeping before rebuilding entries and links
from the oldest entry to the newest. Copy assignment prepares the replacement
before releasing existing entries; exceptions that propagate from allocation or
key/value copying leave both caches intact. This does not guarantee recovery from
allocation inside a standard-library noexcept path: MSVC Debug, for example,
allocates a hash-table iterator proxy in such a constructor.
Insertion of an existing key retains its original value and recency. Insertion
failure from allocation or key/value copying propagates the exception and removes
the incomplete entry; existing values and eviction order remain intact. find()
still promotes a found entry and successful insertion evicts the least recently
used entry when full. Public signatures and class fields are unchanged; rebuild
header consumers to use the fix. check-lru-map, also included in check-core,
covers independent copies, eviction, key-copy exceptions and isolated allocation
failures. Insertion injects failure at every allocation. Copying injects at every
content allocation starting with the first source lookup, after empty container
bookkeeping is ready; it does not inject into MSVC's noexcept proxy construction.
<ark/array_pod.hpp> retains its void mutation APIs and inline/heap storage layout. Use it for trivial scalar or pointer elements with a positive inline capacity; it does not manage nontrivial element lifetimes. push_back, fill resize and insert snapshot an element argument before growing or shifting storage, so an argument such as values[0] keeps its original value. Growth can still invalidate borrowed element pointers and references.
Impossible element/byte capacities throw std::length_error before allocation; a null allocation result throws std::bad_alloc. Allocator exceptions propagate. Failed array growth or copy assignment preserves the existing storage, size and values, and failed copy construction leaves the source unchanged. Callers that handle allocation failure must catch exceptions rather than expect a status return; rebuild affected header consumers and plugins to use the checks. Public signatures and class fields are unchanged.
array_map<std::string, T> keeps borrowed T* values and never deletes pointees. add_element appends the pointer before inserting its name and rolls back the append if index allocation throws. Existing entries, lookup results and count remain consistent; spare pointer capacity or index bucket capacity may have grown. The default pod_string_allocator also converts null allocation results to std::bad_alloc so index failures can propagate. This insertion guarantee does not extend to custom string allocators or all other pod_string operations. Duplicate-name behavior is unchanged. Permanent Core tests cover scalar/pointer aliases, arithmetic limits, null/throwing allocators, copying and pointer/index failure recovery through check-core.
<ark/buffer.hpp> is move-only. Moves transfer unread bytes and capacity; the
source becomes empty and can be written again. get_data() borrows storage that
can move on the next write. remove_data() consumes only a valid unread count.
write(data, len) also accepts readable bytes in its own allocation, including
overlapping ranges. Before compaction or growth it snapshots an internal source
with the existing allocation hooks. A range that starts inside the allocation
and extends beyond it returns false, as does nonempty null input. Empty writes
succeed. Null allocation returns false; allocation exceptions propagate. Failed
snapshot or growth allocation preserves bytes, positions and capacity. External
input must remain readable for the entire call. Public signatures, class fields
and growth-capacity selection are unchanged; rebuild header consumers to use the
fix. check-buffer covers self writes and default/custom allocation failures.
Breaking source change: ARK_TO_STRING, ARRAY_LENTGH, ARK_SRATIC_ASSERT,
ARRAY_CLEAR, MEMORY_CLEAR and MEMORY_CLEAR_POINTER are no longer defined.
| Removed name | Migration |
|---|---|
ARK_TO_STRING(value) |
Include <string> and call std::to_string(value). This is the same standard function previously used by the alias, including its C++20 floating-point formatting. |
ARRAY_LENTGH(array) |
Include <iterator> and use std::size(array) for bounded arrays. If code needs a type's first array extent, include <type_traits> and use std::extent_v<T>; std::size does not accept a raw pointer. |
ARK_SRATIC_ASSERT |
Write static_assert directly. |
ARRAY_CLEAR, MEMORY_CLEAR, MEMORY_CLEAR_POINTER |
These unused helpers are removed without a replacement alias. Choose value initialization, typed assignment or an explicit byte operation according to the object's storage contract; there is no universal safe object-clearing operation. MEMORY_CLEAR_POINTER also contained the invalid token 0xx. |
The existing data and endpoint conversions still call std::to_string with the
same argument types. Numeric output and precision remain unchanged. Array-count
call sites keep their existing int variables, lookup order, enum mappings and
range handling. Remaining allocation, ownership, runtime-assertion, platform,
plugin-registration and byte-order macros retain their existing behavior.
Breaking source change: ark/macros.hpp no longer defines ARK_SLEEP. The
repository has no callers; its three platform definitions were unused. Existing
standard-library sleeps, scheduling and timeouts remain unchanged.
For a finite, nonnegative integer delay in milliseconds, include <chrono> and
<thread> and replace an external call with:
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));The argument expression is evaluated once. Check that its value fits
std::chrono::milliseconds::rep; no intermediate multiplication by 1000 is
needed. Review callers that depended on the former platform-specific integer
conversion or overflow, Windows INFINITE/zero-delay scheduling semantics, or
POSIX usleep return values and signal interruption. sleep_for returns void
and does not preserve those contracts.
See the C++ draft's sleep_for contract,
Windows Sleep
and Apple's usleep manual.