JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwConcepts.h
Go to the documentation of this file.
1/**********************************************************\
2* File: QwConcepts.h *
3* *
4* Architectural enforcement concepts for JAPAN-MOLLER *
5* analysis framework following the Dual-Operator Pattern *
6* *
7* This file defines C++20 concepts to enforce proper *
8* implementation of delegator methods and architectural *
9* patterns as outlined in copilot-instructions.md *
10* *
11* For C++ standards < 20, validation is disabled and *
12* static_asserts always pass to maintain compatibility. *
13\**********************************************************/
14
15#ifndef __QWCONCEPTS__
16#define __QWCONCEPTS__
17
18// System headers
19#include <type_traits>
20
21// Forward declarations for classes used in concepts
22class VQwDataElement;
24class VQwSubsystem;
25class VQwDataHandler;
28
29// Check for C++20 concept support - can be overridden externally
30// External override: Define QW_CONCEPTS_AVAILABLE=0 to disable concepts even in C++20
31// External override: Define QW_CONCEPTS_AVAILABLE=1 to enable (requires C++20 support)
32#ifndef QW_CONCEPTS_AVAILABLE
33 #if __cplusplus >= 202002L
34 #if __has_include(<concepts>)
35 #include <concepts>
36 #define QW_CONCEPTS_AVAILABLE 1
37 #else
38 #define QW_CONCEPTS_AVAILABLE 0
39 #endif
40 #else
41 // For C++17 and earlier, always disable concepts regardless of compiler support
42 #define QW_CONCEPTS_AVAILABLE 0
43 #endif
44#else
45 // QW_CONCEPTS_AVAILABLE was defined externally, respect that setting
46 #if QW_CONCEPTS_AVAILABLE && __cplusplus >= 202002L && __has_include(<concepts>)
47 #include <concepts>
48 // Keep QW_CONCEPTS_AVAILABLE as 1
49 #else
50 // Either disabled externally or C++20/concepts not available
51 #undef QW_CONCEPTS_AVAILABLE
52 #define QW_CONCEPTS_AVAILABLE 0
53 #endif
54#endif
55
56// Forward declarations
57class VQwDataElement;
59class VQwSubsystem;
60
61namespace QwArchitecture {
62
63#if QW_CONCEPTS_AVAILABLE
64//==============================================================================
65// C++20 CONCEPTS FOR DUAL-OPERATOR PATTERN ENFORCEMENT
66//==============================================================================
67
68/**
69 * @brief Concept to check if a type has a type-specific UpdateErrorFlag method
70 *
71 * This concept verifies that a class implements UpdateErrorFlag with its own type,
72 * which is required for the type-specific version in the Dual-Operator Pattern.
73 */
74template<typename T>
75concept HasTypeSpecificUpdateErrorFlag = requires(T& obj, const T& other) {
76 { obj.UpdateErrorFlag(&other) } -> std::same_as<void>;
77};
78
79/**
80 * @brief Concept to check if a type has a polymorphic UpdateErrorFlag delegator
81 *
82 * This concept verifies that a class implements the delegator method that bridges
83 * from VQwDataElement signature to the type-specific signature.
84 */
85template<typename T>
86concept HasPolymorphicUpdateErrorFlag = requires(T& obj, const VQwDataElement* base_ptr) {
87 { obj.UpdateErrorFlag(base_ptr) } -> std::same_as<void>;
88};
89
90/**
91 * @brief Concept to check if a type properly implements the Dual-Operator Pattern
92 * for UpdateErrorFlag methods.
93 *
94 * According to copilot instructions, classes that implement type-specific methods
95 * must also provide delegator methods for polymorphic dispatch.
96 */
97template<typename T>
98concept ImplementsDualOperatorUpdateErrorFlag =
99 HasTypeSpecificUpdateErrorFlag<T> &&
100 HasPolymorphicUpdateErrorFlag<T>;
101
102//==============================================================================
103// CONCEPTS FOR ARITHMETIC OPERATORS
104//==============================================================================
105
106/**
107 * @brief Concept for type-specific arithmetic operators
108 *
109 * Validates that a class implements all required type-specific arithmetic operations
110 * as specified in copilot-instructions.md
111 */
112template<typename T>
113concept HasTypeSpecificArithmetic = requires(T& obj, const T& other) {
114 { obj += other } -> std::same_as<T&>;
115 { obj -= other } -> std::same_as<T&>;
116 { obj.Sum(other, other) } -> std::same_as<void>;
117 { obj.Difference(other, other) } -> std::same_as<void>;
118 { obj.Ratio(other, other) } -> std::same_as<T&>;
119};
120
121/**
122 * @brief Concept for polymorphic arithmetic operators (for VQwDataElement derivatives)
123 *
124 * Validates delegator methods that bridge from base class signatures to type-specific implementations
125 */
126template<typename T>
127concept HasPolymorphicArithmetic = requires(T& obj, const VQwDataElement& base) {
128 { obj += base } -> std::same_as<VQwDataElement&>;
129 { obj -= base } -> std::same_as<VQwDataElement&>;
130 { obj.Sum(base, base) } -> std::same_as<void>;
131 { obj.Difference(base, base) } -> std::same_as<void>;
132 { obj.Ratio(base, base) } -> std::same_as<VQwDataElement&>;
133};
134
135/**
136 * @brief Complete Dual-Operator Pattern for arithmetic operations
137 */
138template<typename T>
139concept ImplementsDualOperatorArithmetic =
140 HasTypeSpecificArithmetic<T> &&
141 HasPolymorphicArithmetic<T>;
142
143//==============================================================================
144// CONCEPTS FOR EVENT CUTS AND DIAGNOSTICS
145//==============================================================================
146
147/**
148 * @brief Concept for type-specific event cuts and diagnostics
149 *
150 * Validates that a class implements all required type-specific event cuts and diagnostics
151 * as specified in copilot-instructions.md
152 * Note: Using standard C++ types to avoid ROOT dependencies in concepts
153 */
154template<typename T>
155concept HasTypeSpecificEventCutsAndDiagnostics = requires(T& obj, const T* other) {
156 { obj.SetSingleEventCuts(0U, 0.0, 0.0, 0.0) } -> std::same_as<void>;
157 { obj.CheckForBurpFail(other) } -> std::same_as<bool>;
158};
159
160/**
161 * @brief Concept for polymorphic event cuts and diagnostics (for VQwDataElement derivatives)
162 *
163 * Validates delegator methods that bridge from base class signatures to type-specific implementations
164 */
165template<typename T>
166concept HasPolymorphicEventCutsAndDiagnostics = requires(T& obj, const VQwDataElement* base) {
167 { obj.SetSingleEventCuts(0U, 0.0, 0.0, 0.0) } -> std::same_as<void>;
168 { obj.CheckForBurpFail(base) } -> std::same_as<bool>;
169};
170
171/**
172 * @brief Complete Dual-Operator Pattern for event cuts and diagnostics
173 */
174template<typename T>
175concept ImplementsDualOperatorEventCutsAndDiagnostics =
176 HasTypeSpecificEventCutsAndDiagnostics<T> &&
177 HasPolymorphicEventCutsAndDiagnostics<T>;
178
179//==============================================================================
180// SPECIALIZED BASE CLASS CONCEPTS
181//==============================================================================
182
183/**
184 * @brief Concept for specialized bases that need polymorphic UpdateErrorFlag
185 *
186 * Some hierarchies introduce specialized abstract bases (VQwBPM, VQwBCM, VQwClock)
187 * that are used polymorphically by container code and must expose virtual hooks.
188 */
189template<typename T>
190concept SpecializedBaseWithPolymorphicUpdateErrorFlag = std::is_abstract_v<T> &&
191 requires(T& obj, const T* typed_ptr) {
192 { obj.UpdateErrorFlag(typed_ptr) } -> std::same_as<void>;
193 };
194
195/**
196 * @brief Concept for specialized bases with CheckForBurpFail support
197 *
198 * Validates that specialized bases like VQwClock, VQwBPM, VQwBCM provide
199 * the necessary virtual hooks for polymorphic dispatch
200 */
201template<typename T>
202concept SpecializedBaseWithPolymorphicCheckForBurpFail = std::is_abstract_v<T> &&
203 requires(T& obj, const T* typed_ptr) {
204 { obj.CheckForBurpFail(typed_ptr) } -> std::same_as<bool>;
205 };
206
207/**
208 * @brief Complete specialized base pattern validation
209 */
210template<typename T>
211concept ImplementsSpecializedBasePattern =
212 SpecializedBaseWithPolymorphicUpdateErrorFlag<T> &&
213 SpecializedBaseWithPolymorphicCheckForBurpFail<T>;
214
215//==============================================================================
216// CONTAINER DELEGATION PATTERN CONCEPTS
217//==============================================================================
218
219/**
220 * @brief Concept for container classes using the Container-Delegation Pattern
221 *
222 * Container classes should use single operator versions and delegate to
223 * contained objects, avoiding virtual operator inheritance issues.
224 * This applies to subsystem arrays and similar collection classes.
225 *
226 * The pattern requires:
227 * 1. Type-specific operators that return the container type
228 * 2. Should NOT have virtual operators with VQwDataElement base signatures
229 *
230 * Critical distinction from Dual-Operator Pattern:
231 * - Container classes use type-specific operators (e.g., QwSubsystemArrayParity += QwSubsystemArrayParity)
232 * - Contained objects use VQwSubsystem operators (for subsystem containers) or VQwDataElement operators (for data element containers)
233 * - Container classes should NEVER use VQwDataElement operators directly
234 */
235template<typename T>
236concept ImplementsContainerDelegationPattern = requires(T& obj, const T& other) {
237 // Container should have type-specific operators only
238 { obj += other } -> std::same_as<T&>;
239 { obj -= other } -> std::same_as<T&>;
240 { obj.Sum(other, other) } -> std::same_as<void>;
241};
242
243/**
244 * @brief Concept for polymorphic subsystem pattern
245 *
246 * Regular subsystems (non-container) should implement VQwSubsystem polymorphic operators
247 * for integration with the framework's polymorphic dispatch system.
248 * This applies to classes like QwOmnivore that act as subsystem implementations.
249 */
250template<typename T>
251concept ImplementsPolymorphicSubsystemPattern = requires(T& obj, VQwSubsystem* other) {
252 // Subsystem should have polymorphic operators with VQwSubsystem base
253 { obj += other } -> std::same_as<VQwSubsystem&>;
254 { obj -= other } -> std::same_as<VQwSubsystem&>;
255 { obj.Sum(other, other) } -> std::same_as<void>;
256};
257
258/**
259 * @brief Helper to determine if a class name suggests it's a container
260 *
261 * Uses compile-time template matching to identify container classes.
262 * Container classes typically have "Array" in their name.
263 */
264template<typename T>
265struct IsContainerClass {
266 static constexpr bool value = false;
267};
268
269// Specialization for QwSubsystemArrayParity and similar array classes
270template<>
271struct IsContainerClass<QwSubsystemArrayParity> {
272 static constexpr bool value = true;
273};
274
275template<>
276struct IsContainerClass<QwSubsystemArray> {
277 static constexpr bool value = true;
278};
279
280//==============================================================================
281// ARCHITECTURAL VALIDATION CONCEPTS
282//==============================================================================
283
284/**
285 * @brief Master concept for VQwDataElement derivatives
286 *
287 * Enforces that concrete VQwDataElement derivatives properly implement
288 * the complete Dual-Operator Pattern for all required methods as specified
289 * in copilot-instructions.md
290 */
291template<typename T>
292concept ValidVQwDataElementDerivative =
293 std::is_base_of_v<VQwDataElement, T> &&
294 !std::is_abstract_v<T> &&
295 ImplementsDualOperatorArithmetic<T> &&
296 ImplementsDualOperatorUpdateErrorFlag<T> &&
297 ImplementsDualOperatorEventCutsAndDiagnostics<T>;
298
299/**
300 * @brief Master concept for VQwHardwareChannel derivatives
301 *
302 * VQwHardwareChannel derivatives must satisfy all VQwDataElement requirements
303 * plus any additional hardware-specific patterns
304 */
305template<typename T>
306concept ValidVQwHardwareChannelDerivative =
307 std::is_base_of_v<VQwHardwareChannel, T> &&
308 !std::is_abstract_v<T> &&
309 ValidVQwDataElementDerivative<T>;
310
311/**
312 * @brief Master concept for specialized abstract bases
313 *
314 * Validates specialized bases like VQwBPM, VQwBCM, VQwClock that provide
315 * polymorphic dispatch points for container code
316 */
317template<typename T>
318concept ValidSpecializedBase =
319 std::is_abstract_v<T> &&
320 std::is_base_of_v<VQwDataElement, T> &&
321 ImplementsSpecializedBasePattern<T>;
322
323/**
324 * @brief Master concept for container classes
325 *
326 * Container classes should use the Container-Delegation Pattern
327 */
328template<typename T>
329concept ValidContainerClass =
330 ImplementsContainerDelegationPattern<T>;
331
332/**
333 * @brief Master concept for polymorphic subsystem classes
334 *
335 * Regular subsystem classes should use polymorphic VQwSubsystem operators
336 */
337template<typename T>
338concept ValidPolymorphicSubsystem =
339 std::is_base_of_v<VQwSubsystem, T> &&
340 !std::is_abstract_v<T> &&
341 ImplementsPolymorphicSubsystemPattern<T>;
342
343/**
344 * @brief Unified subsystem validation concept
345 *
346 * Validates subsystems using appropriate pattern based on class characteristics
347 * Container classes use Container-Delegation Pattern, others use Polymorphic Subsystem Pattern
348 */
349template<typename T>
350concept ValidSubsystemClass =
351 (IsContainerClass<T>::value && ValidContainerClass<T>) ||
352 (!IsContainerClass<T>::value && ValidPolymorphicSubsystem<T>);
353
354#endif // QW_CONCEPTS_AVAILABLE
355
356//==============================================================================
357// STATIC ASSERTION HELPERS (WORK WITH BOTH C++17 AND C++20)
358//==============================================================================
359
360/**
361 * @brief Helper macro to validate architectural compliance in concrete classes
362 *
363 * Usage: VALIDATE_DATA_ELEMENT_PATTERN(MyConcreteClass);
364 *
365 * In C++20: Performs full concept validation for all required methods
366 * In C++17: Always passes but documents architectural requirements
367 */
368#if QW_CONCEPTS_AVAILABLE
369#define VALIDATE_DATA_ELEMENT_PATTERN(ClassName) \
370 static_assert(QwArchitecture::ValidVQwDataElementDerivative<ClassName>, \
371 #ClassName " must implement complete Dual-Operator Pattern for all required methods. " \
372 "See copilot-instructions.md for implementation requirements. " \
373 "(C++20 concept validation active)"); \
374 static_assert(QwArchitecture::HasTypeSpecificUpdateErrorFlag<ClassName>, \
375 #ClassName " must implement type-specific UpdateErrorFlag(const " #ClassName "*) " \
376 "(C++20 concept validation active)"); \
377 static_assert(QwArchitecture::HasPolymorphicUpdateErrorFlag<ClassName>, \
378 #ClassName " must implement polymorphic delegator UpdateErrorFlag(const VQwDataElement*) " \
379 "(C++20 concept validation active)"); \
380 static_assert(QwArchitecture::HasTypeSpecificArithmetic<ClassName>, \
381 #ClassName " must implement type-specific arithmetic operators (+=, -=, Sum, Difference, Ratio) " \
382 "(C++20 concept validation active)"); \
383 static_assert(QwArchitecture::HasPolymorphicArithmetic<ClassName>, \
384 #ClassName " must implement polymorphic arithmetic delegators " \
385 "(C++20 concept validation active)"); \
386 static_assert(QwArchitecture::ImplementsDualOperatorEventCutsAndDiagnostics<ClassName>, \
387 #ClassName " must implement SetSingleEventCuts and CheckForBurpFail patterns " \
388 "(C++20 concept validation active)");
389#else
390#define VALIDATE_DATA_ELEMENT_PATTERN(ClassName) \
391 /* C++17 mode: Architectural patterns documented but validation disabled */ \
392 static_assert(true, #ClassName " architectural requirements documented (upgrade to C++20 for validation)");
393#endif
394
395/**
396 * @brief Helper macro to validate data handler compliance
397 *
398 * Data handlers have different architectural requirements than data elements.
399 * They don't need the Dual-Operator Pattern since they handle data processing
400 * rather than data storage and arithmetic operations.
401 */
402#if QW_CONCEPTS_AVAILABLE
403#define VALIDATE_DATA_HANDLER_PATTERN(ClassName) \
404 static_assert(std::is_base_of_v<VQwDataHandler, ClassName>, \
405 #ClassName " must inherit from VQwDataHandler for factory registration. " \
406 "(C++20 concept validation active)");
407#else
408#define VALIDATE_DATA_HANDLER_PATTERN(ClassName) \
409 /* C++17 mode: Data handler patterns documented but validation disabled */ \
410 static_assert(true, #ClassName " data handler requirements documented (upgrade to C++20 for validation)");
411#endif
412
413/**
414 * @brief Helper macro to validate unified subsystem compliance
415 */
416#if QW_CONCEPTS_AVAILABLE
417#define VALIDATE_SUBSYSTEM_PATTERN(ClassName) \
418 static_assert(QwArchitecture::ValidSubsystemClass<ClassName>, \
419 #ClassName " must implement appropriate subsystem pattern. Containers use Container-Delegation, " \
420 "regular subsystems use Polymorphic Subsystem patterns. " \
421 "(C++20 concept validation active)");
422#else
423#define VALIDATE_SUBSYSTEM_PATTERN(ClassName) \
424 /* C++17 mode: Subsystem patterns documented but validation disabled */ \
425 static_assert(true, #ClassName " subsystem requirements documented (upgrade to C++20 for validation)");
426#endif
427
428} // namespace QwArchitecture
429
430#endif // __QWCONCEPTS__
Container for managing multiple subsystems with common operations.
The pure virtual base class of all data elements.
Abstract base for concrete hardware channels implementing dual-operator pattern.
Base class for subsystems implementing container-delegation pattern.
Subsystem array container specialized for parity analysis with asymmetry calculations.
Abstract base for handlers that consume multiple subsystems and produce derived outputs.