ores.cpp.domain.class_header
Table of Contents
The entity's value type: members from the model's columns plus valid_from / valid_to. domain profile. A plain C++ aggregate `struct` — no user-declared constructors, copyable, movable, and aggregate-initialisable. Relies on reflect-cpp (via the companion `_json_io` archetype) for serialisation; the domain type itself carries no serialisation code.
See the Template variable reference for the complete list of available variables and their semantics.
1. Template
The full template source. Edit here and re-tangle with
compass build --direct tangle_codegen_templates to regenerate
library/templates/cpp_domain_type_class.hpp.mustache.
{{! GENERATED FILE — tangled from projects/ores.codegen/library/templates/cpp_domain.org. Edit the org source. }}
{{{cpp_license}}}
{{#domain_entity}}
#ifndef ORES_{{component_include_upper}}_DOMAIN_{{entity_singular_upper}}_HPP
#define ORES_{{component_include_upper}}_DOMAIN_{{entity_singular_upper}}_HPP
{{#cpp.includes.domain}}
#include {{{.}}}
{{/cpp.includes.domain}}
{{#has_base64_columns}}
#include <cstdint>
#include <vector>
{{/has_base64_columns}}
{{^has_domain_groups}}
{{^has_identity_group}}
{{#has_tenant_id}}
#include "ores.utility/uuid/tenant_id.hpp"
{{/has_tenant_id}}
{{/has_identity_group}}
{{/has_domain_groups}}
#include <string_view>
namespace ores::{{component}}::domain {
/**
* @brief {{{brief}}}
*
{{#description_lines}}
*{{#.}} {{{.}}}{{/.}}
{{/description_lines}}
*/
struct {{entity_singular}} final {
{{#has_domain_groups}}
{{#domain_groups}}
{{{type_qualified}}} {{member}};
{{/domain_groups}}
{{/has_domain_groups}}
{{^has_domain_groups}}
{{#has_identity_group}}
{{identity_group_type}} identity;
{{/has_identity_group}}
{{^has_identity_group}}
{{#has_audit_columns}}
/**
* @brief Version number for optimistic locking and change tracking.
*/
int version = 0;
{{/has_audit_columns}}
{{#has_tenant_id}}
/**
* @brief Tenant identifier for multi-tenancy isolation.
*/
{{#nullable_tenant_id}}
std::optional<utility::uuid::tenant_id> tenant_id;
{{/nullable_tenant_id}}
{{^nullable_tenant_id}}
utility::uuid::tenant_id tenant_id = utility::uuid::tenant_id::system();
{{/nullable_tenant_id}}
{{/has_tenant_id}}
{{#has_workspace_id}}
/**
* @brief Workspace this record belongs to.
*
* Defaults to the Live workspace sentinel.
*/
boost::uuids::uuid workspace_id = utility::uuid::live_workspace_id();
{{/has_workspace_id}}
{{#primary_key.columns}}
/**
* @brief {{{description}}}
{{#detail}}
*
* {{{detail}}}
{{/detail}}
*/
{{{cpp_type}}} {{column}};
{{/primary_key.columns}}
{{#natural_keys}}
/**
* @brief {{{description}}}
{{#detail}}
*
* {{{detail}}}
{{/detail}}
*/
{{{cpp_type}}} {{column}}{{#default_value}} = {{{default_value}}}{{/default_value}};
{{/natural_keys}}
{{/has_identity_group}}
{{#columns}}
{{^is_identity_group_column}}
{{^sql_only}}
/**
* @brief {{{description}}}
{{#detail}}
*
* {{{detail}}}
{{/detail}}
*/
{{{cpp_type}}} {{name}}{{#default_value}} = {{{default_value}}}{{/default_value}};
{{/sql_only}}
{{/is_identity_group_column}}
{{/columns}}
{{#has_audit_group}}
{{{audit_group_qualified}}} audit;
{{/has_audit_group}}
{{^has_audit_group}}
{{#has_audit_columns}}
/**
* @brief Username of the person who last modified this {{entity_singular_words}}.
*/
std::string modified_by;
/**
* @brief Username of the account that performed this action.
*/
std::string performed_by;
/**
* @brief Code identifying the reason for the change.
*
* References change_reasons table (soft FK).
*/
std::string change_reason_code;
/**
* @brief Free-text commentary explaining the change.
*/
std::string change_commentary;
/**
* @brief Timestamp when this version of the record was recorded.
*
* The transaction-time window's start, which the store sets from its own
* clock. It travels with the audit members because it is only ever read
* with them: the history builder takes a version type that carries an
* actor *and* this timestamp, so an entity without the actor has no use
* for the timestamp either.
*/
std::chrono::system_clock::time_point recorded_at;
{{/has_audit_columns}}
{{/has_audit_group}}
{{/has_domain_groups}}
/**
* @brief Value equality.
*
* Every generated domain type is a value: two of them are equal when their
* members are, whatever the entity means. A test that round-trips one
* through the wire asserts exactly that, so equality is part of the shape
* rather than something each entity decides -- an entity without it cannot
* be round-trip tested at all, which is why the omission went unnoticed
* until the diff payloads were the first generated types to have a test.
*/
friend bool operator==(const {{entity_singular}}&, const {{entity_singular}}&) = default;
};
/**
* @brief Dispatch-key identifier for {{entity_singular}}, e.g. for the
* generic history-diff request and action registries. Single source
* of truth: every call site spells entity_type_of(value) regardless
* of which entity it holds.
*/
[[nodiscard]] constexpr std::string_view entity_type_of(const {{entity_singular}}&) {
return "ores.{{component}}.{{entity_singular}}";
}
}
#endif
{{/domain_entity}}
{{#junction}}
#ifndef ORES_{{component_upper}}_DOMAIN_{{name_singular_upper}}_HPP
#define ORES_{{component_upper}}_DOMAIN_{{name_singular_upper}}_HPP
{{#cpp.includes.domain}}
#include {{{.}}}
{{/cpp.includes.domain}}
{{#has_base64_columns}}
#include <cstdint>
#include <vector>
{{/has_base64_columns}}
#include <string_view>
namespace ores::{{component}}::domain {
/**
* @brief {{{brief}}}
*
{{#description_lines}}
*{{#.}} {{{.}}}{{/.}}
{{/description_lines}}
*/
struct {{name_singular}} final {
/**
* @brief Version number for optimistic locking and change tracking.
*/
int version = 0;
{{#has_tenant_id}}
/**
* @brief Tenant identifier for multi-tenancy isolation.
*/
std::string tenant_id;
{{/has_tenant_id}}
/**
* @brief {{{left.description}}}
{{#left.detail}}
*
* {{{left.detail}}}
{{/left.detail}}
*/
{{{left.cpp_type}}} {{left.column}};
/**
* @brief {{{right.description}}}
{{#right.detail}}
*
* {{{right.detail}}}
{{/right.detail}}
*/
{{{right.cpp_type}}} {{right.column}};
{{#columns}}
/**
* @brief {{{description}}}
{{#detail}}
*
* {{{detail}}}
{{/detail}}
*/
{{{cpp_type}}} {{name}}{{#default_value}} = {{{default_value}}}{{/default_value}};
{{/columns}}
/**
* @brief Username of the person who last modified this {{name_singular_words}}.
*/
std::string modified_by;
/**
* @brief Username of the account that performed this action.
*/
std::string performed_by;
/**
* @brief Code identifying the reason for the change.
*
* References change_reasons table (soft FK).
*/
std::string change_reason_code;
/**
* @brief Free-text commentary explaining the change.
*/
std::string change_commentary;
/**
* @brief Timestamp when this version of the record was recorded.
*/
std::chrono::system_clock::time_point recorded_at;
<<paste:B1E09FE1-51D0-49DF-BDF4-2610598C8A1C>>
/**
* @brief Value equality, on the same terms as an entity's.
*/
friend bool operator==(const {{name_singular}}&, const {{name_singular}}&) = default;
};
/**
* @brief Dispatch-key identifier for {{name_singular}}, e.g. for the
* generic history-diff request and action registries. Single source
* of truth: every call site spells entity_type_of(value) regardless
* of which entity it holds.
*/
[[nodiscard]] constexpr std::string_view entity_type_of(const {{name_singular}}&) {
return "ores.{{component}}.{{name_singular}}";
}
}
#endif
{{/junction}}
2. See also
- Parent facet: ores.cpp.domain
- Template variable reference