Class Design Implementation Specification

Purpose

This validator enforces consistency between the class model in the unit design and the class model extracted from the implementation.

It shall make sure that every class and free function, as well as every class member, method, enum literal, type alias, and relationship modeled in the unit design, exists in the implementation and is compatible with it.

Implementation-only entities and members are allowed. The unit design is the validated contract.

What is Validated

The validator compares unit design class diagrams with implementation class diagrams produced by the C++ parser. It receives two indexed class-diagram inputs:

Input

Source

Meaning

design_classes

unit_design class diagram FlatBuffers

Required class model from the unit design

implementation_classes

C++ parser class diagram FlatBuffers from unit implementation targets

Observed class model from implementation code

Entity Presence and Type Consistency

Every entity in the unit design class diagram must have a corresponding entity in the implementation class diagram. Matching entities must have the same entity type. (Requirement: Tools.ClassDesignImplementationEntityConsistency)

This item covers entity matching and entity type only. The consistency of data contained by a matched entity is covered by the following type alias, variable, method, enum literal, relationship, and template parameter items.

If the same class ID is declared more than once across the unit design’s input class diagrams (e.g. an overview and a detail .puml file), the declarations merge when at most one of them has a body (members, type aliases or enum literals); the relationships of all declarations are united. Two declarations with a body are reported as a failure naming both source locations, independent of entity type consistency. A different entity type or stereotype across the declarations is a failure as well. (Requirement: Tools.ClassDesignImplementationDeclarationMerge)

' PlantUML class diagram
package vehicle {
  class "Transport"
}
// implementation C++ code
namespace vehicle {
  class Transport {}
}

Template Parameter Consistency

Template parameters modeled on unit design entities and methods must match the template parameters on the corresponding implementation entities and methods. (Requirement: Tools.ClassDesignImplementationTemplateParameterConsistency)

For classes, methods, and free functions:

  • Parameters match by position, count, kind, and pack marker. Non-type parameter types are normalized before comparison; template-template parameters are compared recursively.

  • Omitted design names are unconstrained; explicit names must match. An absent parameter list is not a wildcard.

Specialization exception: implementation partial and explicit full specializations are matched by fully qualified base name only. Their class template parameters and specialization arguments are not validated against the design. This exception does not apply to method template parameters. A debug diagnostic explains when the class template-parameter check is skipped.

When matching partial or explicit full specializations exist, a matching primary template is included in implementation consistency checks only if its template parameters match the design. This allows rejection-only primary templates to be excluded from a specialization’s interface contract; the validator does not determine whether a primary template serves that purpose. Without matching specializations, the primary template is checked normally, including template-parameter mismatches. Ordinary non-template classes are not subject to this primary-template filtering rule.

Notation: type, non-type, and template-template parameters support optional names and packs: typename... Ts, int... Ns, and template<typename> class... Cs. class and typename are interchangeable for type parameters and template-template parameter tails. Packs precede explicit names (typename Ts... is unsupported). Legacy T and Ts... denote type parameters; unnamed non-type parameters require built-in or unambiguous compound types such as int, std::size_t, or int*.

Scope: this is a modeling subset, not C++ declaration validation. Defaults, constraints, and complex declarators are unsupported; type lookup and semantic validity remain the C++ compiler’s responsibility. An unsupported template list in a quoted name produces no template parameter metadata.

' PlantUML class diagram
class Repository<T> {
  + FindById<Key>(id: Key) : T
}
// implementation C++ code
template <typename T>
class Repository {
  template <typename Key>
  T FindById(Key id);
}

Specialization Interface Matching

A quoted class name may describe a partial or explicit full specialization. Its trailing template arguments are removed from the design entity ID; an alias does not change that ID.

The declared interface is checked against every implementation partial or explicit full specialization with the same fully qualified base name, without comparing its class template parameters or specialization arguments. The raw design <…> text is not retained for argument comparison, so a typo such as <ReturnTyp(ArgTypes...), Capacity, Alignment> or an unrelated list such as <int, X> does not cause a specialization-argument mismatch. A debug diagnostic identifies each skipped class template-parameter check and explains this base-name-only matching limitation.

The design therefore defines one shared contract, not separate contracts per specialization. Multiple patterns resolve to the same ID and follow the declaration-merge rules above; conflicting declarations fail before implementation comparison.

For example, a design entity Box is checked against both Box<int> and Box<double> explicit full specializations. A design label Box<int> still resolves to the base ID Box; it does not select only the int specialization. Each specialization must satisfy the shared member and method contract, including method template parameters. No template-argument substitution is performed when comparing member or method types.

Explicit instantiation definitions (template class Box<double>;) and declarations (extern template class Box<float>;) reuse an existing template implementation; they do not define independent interfaces. The C++ extractor excludes these declarations and their member traversal from the implementation class model. Their concrete type names remain available when referenced by other declarations. Implicit uses likewise do not introduce independent interface contracts.

For template-associated class cursors, the extractor distinguishes template <> specialization headers from explicit instantiation headers using declaration tokens, ignoring comments. An unrecognized header (for example an unsupported macro expansion) produces a warning and is not collected; it is never silently classified as a non-template class or an explicit specialization. Such warnings indicate an incomplete extracted model and must be investigated before relying on validation.

' One design entity; the interface is checked against each matching specialization.
namespace amp {
  class "move_only_function<ReturnType(ArgTypes...), Capacity, Alignment>" as move_only_function {
    + empty() noexcept : bool
  }
}

Type Alias Consistency

Every type alias modeled in the unit design entity must exist in the matching implementation entity. The alias name and normalized original type must match. (Requirement: Tools.ClassDesignImplementationTypeAliasConsistency)

' PlantUML class diagram
class "Transport" {
  using Payload = std::uint8_t
}
// implementation C++ code
class Transport {
public:
  using Payload = std::uint8_t;
};

Variable Consistency

Every variable modeled in the unit design entity must exist in the matching implementation entity. The variable name, normalized data type, visibility, and static flag must match. (Requirement: Tools.ClassDesignImplementationVariableConsistency)

' PlantUML class diagram
class "Transport" {
  - buffer: std::uint8_t*
  {static} - instance_count: uint32_t
}
// implementation C++ code
class Transport {
private:
  std::uint8_t* buffer;
  static std::uint32_t instance_count;
};

Method Consistency

Every method modeled in the unit design entity must exist in the matching implementation entity. The method name, visibility, parameters, and method modifiers must match, and the normalized return type must also match (this applies to constructors and destructors too, which typically have no return type on either side). Method modifiers include static, virtual, abstract, override, constructor, destructor, and noexcept. Parameters match when they have the same count, with matching parameter name, normalized type, and pack-expansion (...) marker at each position. (Requirement: Tools.ClassDesignImplementationMethodConsistency)

static, abstract, virtual, and override may each be written either as a brace qualifier (e.g. {virtual}) or as a stereotype (e.g. <<virtual>>); both forms are equivalent. override may additionally be written as a bare trailing keyword after the method signature, mirroring C++ syntax, e.g. + Run() override. noexcept is only written as a bare trailing keyword, e.g. + Run() noexcept. An abstract or override method is implicitly virtual (matching C++ semantics), so the effective modifier set includes virtual even if it was not written explicitly. The visibility classifier (+/-/#/~) is always written first, before any brace/stereotype modifier, e.g. + {virtual} Run().

' PlantUML class diagram
class "Base" {
  + {virtual} Run(): void
  + {virtual} Stop(): void
}
class "Transport" {
  + <<override>> Run(): void
  + Stop() override : void
  + Tick() noexcept : void
}
Base <|-- Transport
// implementation C++ code
class Base {
public:
  virtual void Run();
  virtual void Stop();
};

class Transport : public Base {
public:
  void Run() override;
  void Stop() override;
  void Tick() noexcept;
};

C-style variadic parameters (e.g. void Log(const char* fmt, ...)) are not currently supported by the PlantUML parser and are not validated: a design parameter is always treated as non-variadic.

Method lookup first tries the full normalized signature. If no exact signature match exists and exactly one implementation method has the same name, that method is compared to produce field-level diagnostics. If multiple same-named implementation overloads exist, the design method is reported as missing because the validator cannot safely choose a candidate.

' PlantUML class diagram
class "Transport" {
  + Dispatch(mode: std::uint8_t, payload: vehicle::Payload): bool
}
// implementation C++ code
bool Transport::Dispatch(std::uint8_t mode, vehicle::Payload payload)

Enum Literal Consistency

Every enum literal modeled in the unit design enum must exist in the matching implementation enum. The full literal data must match. (Requirement: Tools.ClassDesignImplementationEnumLiteralConsistency)

' PlantUML class diagram
enum "Mode" {
  Startup
  Shutdown
}
// implementation C++ code
enum Mode {
  Startup,
  Shutdown,
};

Relationship Consistency

Every relationship modeled on a unit design entity must exist on the matching implementation entity. Source, target, and relationship type must match. (Requirement: Tools.ClassDesignImplementationRelationshipConsistency)

' PlantUML class diagram
struct Payload {}
class Vehicle {
  + Load(payload : Payload)
}
Vehicle ..> Payload
// implementation C++ code
struct Payload {};
class Vehicle {
public:
  void Load(Payload payload);
};

Free Function Consistency

Every free function (at global or namespace scope) modeled in the unit design must exist in the implementation. Functions are matched by their namespace-qualified name and normalized parameter types, which supports overloads. Return type, parameter names and types, variadic or pack-expansion markers, and template parameters must match. (Requirement: Tools.ClassDesignImplementationFreeFunctionConsistency)

' PlantUML class diagram
namespace vehicle {
  entity VehicleFuncs <<function>> {
    + Dispatch(mode: std::uint8_t): void
  }
}
// implementation C++ code
namespace vehicle {
void Dispatch(std::uint8_t mode);
}

Type Normalization

Before comparing types, the validator applies limited normalization. (Requirement: Tools.ClassDesignImplementationTypeNormalization)

Input form

Normalized form

std::uint8_t

uint8_t

uint8_t *

uint8_t*

Payload &

Payload&

vehicle.Engine

vehicle::Engine

The last row accounts for a difference between the class diagram and implementation parser UIDs: dots used as namespace separators are converted to :: before comparison. This applies to type names, class/entity IDs, and relationship source/target identifiers alike. cv-qualifiers such as const and volatile, and the pointer/reference decorators */&, are preserved (only the spacing around them is normalized).

The class diagram reader already rewrites :: to . in class/entity IDs, enclosing namespace IDs, and relationship endpoints of both inputs, so sequence validators and this validator compare IDs in the same form. Type names are read as written and normalized only here.

Failure Cases

Failure case

Validation rule

Duplicate class ID across unit design class diagrams

Entity Presence and Type Consistency

Missing implementation entity

Entity Presence and Type Consistency

Entity type mismatch

Entity Presence and Type Consistency

Entity template parameter mismatch

Template Parameter Consistency

Missing type alias

Type Alias Consistency

Type alias original type mismatch

Type Alias Consistency

Missing variable

Variable Consistency

Variable type, visibility, or static flag mismatch

Variable Consistency

Missing method

Method Consistency

Method return type, visibility, parameter, or modifier mismatch

Method Consistency

Method template parameter mismatch

Template Parameter Consistency

Missing enum literal

Enum Literal Consistency

Enum literal data mismatch

Enum Literal Consistency

Missing relationship

Relationship Consistency

Relationship source, target, or type mismatch

Relationship Consistency

Debug Output

The validator emits debug output containing:

  • the design entity ID being compared

  • the implementation entity ID being compared

  • detailed design entity snapshots at trace level

  • detailed implementation entity snapshots at trace level

  • type aliases, variables, methods, template parameters, enum literals, and relationships for each matched entity

Failure messages contain source file and source line information when available. Missing or empty source metadata is rendered as <unknown>.