├── .clang-format ├── .clang-tidy ├── .gitattributes ├── .github └── workflows │ └── tests.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake └── field_reflectionConfig.cmake.in ├── include └── field_reflection.hpp └── test ├── CMakeLists.txt └── test.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -4 4 | AlignAfterOpenBracket: Align 5 | AlignArrayOfStructures: None 6 | AlignConsecutiveAssignments: 7 | Enabled: false 8 | AcrossEmptyLines: false 9 | AcrossComments: false 10 | AlignCompound: false 11 | PadOperators: true 12 | AlignConsecutiveBitFields: 13 | Enabled: false 14 | AcrossEmptyLines: false 15 | AcrossComments: false 16 | AlignCompound: false 17 | PadOperators: true 18 | AlignConsecutiveDeclarations: 19 | Enabled: false 20 | AcrossEmptyLines: false 21 | AcrossComments: false 22 | AlignCompound: false 23 | PadOperators: true 24 | AlignConsecutiveMacros: 25 | Enabled: false 26 | AcrossEmptyLines: false 27 | AcrossComments: false 28 | AlignCompound: false 29 | PadOperators: true 30 | AlignConsecutiveShortCaseStatements: 31 | Enabled: false 32 | AcrossEmptyLines: false 33 | AcrossComments: false 34 | AlignCaseColons: false 35 | AlignEscapedNewlines: Left 36 | AlignOperands: Align 37 | AlignTrailingComments: 38 | Kind: Always 39 | OverEmptyLines: 1 40 | AllowAllArgumentsOnNextLine: true 41 | AllowAllParametersOfDeclarationOnNextLine: true 42 | AllowShortBlocksOnASingleLine: Empty 43 | AllowShortCaseLabelsOnASingleLine: false 44 | AllowShortEnumsOnASingleLine: true 45 | AllowShortFunctionsOnASingleLine: All 46 | AllowShortIfStatementsOnASingleLine: WithoutElse 47 | AllowShortLambdasOnASingleLine: All 48 | AllowShortLoopsOnASingleLine: true 49 | AlwaysBreakAfterDefinitionReturnType: None 50 | AlwaysBreakAfterReturnType: None 51 | AlwaysBreakBeforeMultilineStrings: true 52 | AlwaysBreakTemplateDeclarations: Yes 53 | AttributeMacros: 54 | - __capability 55 | BinPackArguments: true 56 | BinPackParameters: true 57 | BitFieldColonSpacing: Both 58 | BraceWrapping: 59 | AfterCaseLabel: true 60 | AfterClass: true 61 | AfterControlStatement: Always 62 | AfterEnum: true 63 | AfterExternBlock: true 64 | AfterFunction: true 65 | AfterNamespace: true 66 | AfterObjCDeclaration: true 67 | AfterStruct: true 68 | AfterUnion: true 69 | BeforeCatch: true 70 | BeforeElse: true 71 | BeforeLambdaBody: false 72 | BeforeWhile: false 73 | IndentBraces: false 74 | SplitEmptyFunction: true 75 | SplitEmptyRecord: true 76 | SplitEmptyNamespace: true 77 | BreakAfterAttributes: Never 78 | BreakAfterJavaFieldAnnotations: false 79 | BreakArrays: true 80 | BreakBeforeBinaryOperators: None 81 | BreakBeforeConceptDeclarations: Always 82 | BreakBeforeBraces: Custom 83 | BreakBeforeInlineASMColon: OnlyMultiline 84 | BreakBeforeTernaryOperators: true 85 | BreakConstructorInitializers: BeforeColon 86 | BreakInheritanceList: BeforeColon 87 | BreakStringLiterals: true 88 | ColumnLimit: 120 89 | CommentPragmas: '^( IWYU pragma:|/ | TODO)' 90 | CompactNamespaces: false 91 | ConstructorInitializerIndentWidth: 4 92 | ContinuationIndentWidth: 4 93 | Cpp11BracedListStyle: true 94 | DerivePointerAlignment: true 95 | DisableFormat: false 96 | EmptyLineAfterAccessModifier: Never 97 | EmptyLineBeforeAccessModifier: LogicalBlock 98 | ExperimentalAutoDetectBinPacking: false 99 | FixNamespaceComments: true 100 | ForEachMacros: 101 | - foreach 102 | - Q_FOREACH 103 | - BOOST_FOREACH 104 | IfMacros: 105 | - KJ_IF_MAYBE 106 | IncludeBlocks: Preserve 107 | IncludeCategories: 108 | - Regex: '^' 109 | Priority: 2 110 | SortPriority: 0 111 | CaseSensitive: false 112 | - Regex: '^<.*\.h>' 113 | Priority: 1 114 | SortPriority: 0 115 | CaseSensitive: false 116 | - Regex: '^<.*' 117 | Priority: 2 118 | SortPriority: 0 119 | CaseSensitive: false 120 | - Regex: '.*' 121 | Priority: 3 122 | SortPriority: 0 123 | CaseSensitive: false 124 | IncludeIsMainRegex: '([-_](test|unittest))?$' 125 | IncludeIsMainSourceRegex: '' 126 | IndentAccessModifiers: false 127 | IndentCaseBlocks: false 128 | IndentCaseLabels: true 129 | IndentExternBlock: AfterExternBlock 130 | IndentGotoLabels: true 131 | IndentPPDirectives: None 132 | IndentRequiresClause: false 133 | IndentWidth: 4 134 | IndentWrappedFunctionNames: false 135 | InsertBraces: false 136 | InsertNewlineAtEOF: false 137 | InsertTrailingCommas: None 138 | IntegerLiteralSeparator: 139 | Binary: 0 140 | BinaryMinDigits: 0 141 | Decimal: 0 142 | DecimalMinDigits: 0 143 | Hex: 0 144 | HexMinDigits: 0 145 | JavaScriptQuotes: Leave 146 | JavaScriptWrapImports: true 147 | KeepEmptyLinesAtTheStartOfBlocks: false 148 | KeepEmptyLinesAtEOF: false 149 | LambdaBodyIndentation: Signature 150 | LineEnding: DeriveLF 151 | MacroBlockBegin: '' 152 | MacroBlockEnd: '' 153 | MaxEmptyLinesToKeep: 1 154 | NamespaceIndentation: All 155 | ObjCBinPackProtocolList: Auto 156 | ObjCBlockIndentWidth: 4 157 | ObjCBreakBeforeNestedBlockParam: true 158 | ObjCSpaceAfterProperty: false 159 | ObjCSpaceBeforeProtocolList: false 160 | PackConstructorInitializers: NextLine 161 | PenaltyBreakAssignment: 2 162 | PenaltyBreakBeforeFirstCallParameter: 1 163 | PenaltyBreakComment: 300 164 | PenaltyBreakFirstLessLess: 120 165 | PenaltyBreakOpenParenthesis: 0 166 | PenaltyBreakString: 1000 167 | PenaltyBreakTemplateDeclaration: 10 168 | PenaltyExcessCharacter: 1000000 169 | PenaltyIndentedWhitespace: 0 170 | PenaltyReturnTypeOnItsOwnLine: 200 171 | PointerAlignment: Left 172 | PPIndentWidth: -1 173 | QualifierAlignment: Leave 174 | RawStringFormats: 175 | - Language: TextProto 176 | CanonicalDelimiter: '' 177 | BasedOnStyle: google 178 | ReferenceAlignment: Pointer 179 | ReflowComments: true 180 | RemoveBracesLLVM: false 181 | RemoveParentheses: Leave 182 | RemoveSemicolon: false 183 | RequiresClausePosition: OwnLine 184 | RequiresExpressionIndentation: OuterScope 185 | SeparateDefinitionBlocks: Leave 186 | ShortNamespaceLines: 1 187 | SortIncludes: CaseSensitive 188 | SortJavaStaticImport: Before 189 | SortUsingDeclarations: LexicographicNumeric 190 | SpaceAfterCStyleCast: false 191 | SpaceAfterLogicalNot: false 192 | SpaceAfterTemplateKeyword: true 193 | SpaceAroundPointerQualifiers: Default 194 | SpaceBeforeAssignmentOperators: true 195 | SpaceBeforeCaseColon: false 196 | SpaceBeforeCpp11BracedList: false 197 | SpaceBeforeCtorInitializerColon: true 198 | SpaceBeforeInheritanceColon: true 199 | SpaceBeforeJsonColon: false 200 | SpaceBeforeParens: Custom 201 | SpaceBeforeParensOptions: 202 | AfterControlStatements: true 203 | AfterForeachMacros: true 204 | AfterFunctionDefinitionName: false 205 | AfterFunctionDeclarationName: false 206 | AfterIfMacros: true 207 | AfterOverloadedOperator: false 208 | AfterRequiresInClause: true 209 | AfterRequiresInExpression: false 210 | BeforeNonEmptyParentheses: false 211 | SpaceBeforeRangeBasedForLoopColon: true 212 | SpaceBeforeSquareBrackets: false 213 | SpaceInEmptyBlock: false 214 | SpacesBeforeTrailingComments: 2 215 | SpacesInAngles: Never 216 | SpacesInContainerLiterals: true 217 | SpacesInLineCommentPrefix: 218 | Minimum: 1 219 | Maximum: -1 220 | SpacesInParens: Never 221 | SpacesInParensOptions: 222 | InCStyleCasts: false 223 | InConditionalStatements: false 224 | InEmptyParentheses: false 225 | Other: false 226 | SpacesInSquareBrackets: false 227 | Standard: Auto 228 | StatementAttributeLikeMacros: 229 | - Q_EMIT 230 | StatementMacros: 231 | - Q_UNUSED 232 | - QT_REQUIRE_VERSION 233 | TabWidth: 4 234 | UseTab: Never 235 | VerilogBreakBetweenInstancePorts: true 236 | WhitespaceSensitiveMacros: 237 | - STRINGIZE 238 | - PP_STRINGIZE 239 | - BOOST_PP_STRINGIZE 240 | - NS_SWIFT_NAME 241 | - CF_SWIFT_NAME 242 | ... 243 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: 'clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,clang-diagnostic-*,clang-analyzer-*,-*,google-*,modernize-*,performance-*,portability-*,readability-*,clang-diagnostic-*,clang-analyzer-*,-modernize-pass-by-value,-modernize-use-trailing-return-type,-google-readability-todo,-google-readability-braces-around-statements,-google-runtime-references,-readability-named-parameter,-readability-braces-around-statements,-readability-redundant-declaration,-readability-function-cognitive-complexity,-readability-qualified-auto,-readability-identifier-length' 3 | WarningsAsErrors: '' 4 | HeaderFilterRegex: '.*' 5 | AnalyzeTemporaryDtors: false 6 | FormatStyle: file 7 | CheckOptions: 8 | 9 | - key: readability-identifier-naming.PointerParameterPrefix 10 | value: '' 11 | - key: readability-suspicious-call-argument.PrefixSimilarAbove 12 | value: '30' 13 | - key: modernize-replace-disallow-copy-and-assign-macro.MacroName 14 | value: DISALLOW_COPY_AND_ASSIGN 15 | - key: readability-identifier-naming.GlobalConstantIgnoredRegexp 16 | value: '' 17 | - key: modernize-use-auto.MinTypeNameLength 18 | value: '5' 19 | - key: readability-identifier-naming.VirtualMethodPrefix 20 | value: '' 21 | - key: readability-identifier-naming.ConstantMemberSuffix 22 | value: '' 23 | - key: readability-identifier-naming.ConstantParameterPrefix 24 | value: '' 25 | - key: readability-identifier-naming.InlineNamespacePrefix 26 | value: '' 27 | - key: readability-identifier-naming.GlobalConstantPointerIgnoredRegexp 28 | value: '' 29 | - key: readability-inconsistent-declaration-parameter-name.Strict 30 | value: 'false' 31 | - key: readability-identifier-naming.LocalPointerSuffix 32 | value: '' 33 | - key: readability-identifier-naming.StaticVariableIgnoredRegexp 34 | value: '' 35 | - key: readability-identifier-naming.ClassMemberSuffix 36 | value: _ 37 | - key: readability-identifier-naming.ConstexprFunctionSuffix 38 | value: '' 39 | - key: readability-suspicious-call-argument.DiceDissimilarBelow 40 | value: '60' 41 | - key: readability-identifier-naming.GlobalPointerIgnoredRegexp 42 | value: '' 43 | - key: readability-identifier-naming.TemplateTemplateParameterPrefix 44 | value: '' 45 | - key: readability-identifier-naming.StaticVariableCase 46 | value: lower_case 47 | - key: readability-suspicious-call-argument.Equality 48 | value: 'true' 49 | - key: readability-identifier-naming.EnumConstantSuffix 50 | value: '' 51 | - key: readability-identifier-naming.ParameterIgnoredRegexp 52 | value: '' 53 | - key: readability-identifier-naming.GlobalConstantPointerCase 54 | value: CamelCase 55 | - key: readability-identifier-naming.EnumConstantCase 56 | value: CamelCase 57 | - key: readability-identifier-naming.StaticConstantIgnoredRegexp 58 | value: '' 59 | - key: readability-identifier-naming.GlobalPointerSuffix 60 | value: '' 61 | - key: readability-identifier-naming.EnumIgnoredRegexp 62 | value: '' 63 | - key: readability-identifier-naming.MemberIgnoredRegexp 64 | value: '' 65 | - key: readability-identifier-naming.ClassMethodSuffix 66 | value: '' 67 | - key: readability-identifier-naming.LocalVariableCase 68 | value: lower_case 69 | - key: readability-identifier-naming.ValueTemplateParameterSuffix 70 | value: '' 71 | - key: readability-identifier-naming.ConstantMemberPrefix 72 | value: '' 73 | - key: modernize-use-nodiscard.ReplacementString 74 | value: '[[nodiscard]]' 75 | - key: modernize-loop-convert.MakeReverseRangeHeader 76 | value: '' 77 | - key: readability-identifier-naming.GlobalConstantSuffix 78 | value: '' 79 | - key: readability-identifier-naming.EnumCase 80 | value: CamelCase 81 | - key: readability-identifier-naming.MethodIgnoredRegexp 82 | value: '' 83 | - key: readability-identifier-naming.ClassMethodCase 84 | value: lower_case 85 | - key: readability-suspicious-call-argument.SuffixSimilarAbove 86 | value: '30' 87 | - key: readability-identifier-naming.LocalPointerPrefix 88 | value: '' 89 | - key: readability-identifier-naming.ConstexprFunctionPrefix 90 | value: '' 91 | - key: readability-identifier-naming.ClassMemberPrefix 92 | value: '' 93 | - key: readability-identifier-naming.ParameterPackCase 94 | value: lower_case 95 | - key: modernize-loop-convert.UseCxx20ReverseRanges 96 | value: 'true' 97 | - key: readability-identifier-naming.ConstantSuffix 98 | value: '' 99 | - key: google-readability-function-size.LineThreshold 100 | value: '4294967295' 101 | - key: performance-type-promotion-in-math-fn.IncludeStyle 102 | value: llvm 103 | - key: readability-function-cognitive-complexity.DescribeBasicIncrements 104 | value: 'true' 105 | - key: readability-identifier-naming.PrivateMemberSuffix 106 | value: _ 107 | - key: readability-identifier-naming.ClassMemberCase 108 | value: lower_case 109 | - key: readability-identifier-naming.EnumConstantPrefix 110 | value: '' 111 | - key: modernize-loop-convert.MakeReverseRangeFunction 112 | value: '' 113 | - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros 114 | value: 'true' 115 | - key: readability-identifier-naming.StaticConstantSuffix 116 | value: '' 117 | - key: readability-identifier-naming.TypeTemplateParameterIgnoredRegexp 118 | value: '' 119 | - key: readability-identifier-naming.IgnoreFailedSplit 120 | value: 'false' 121 | - key: readability-qualified-auto.AddConstToQualified 122 | value: 'true' 123 | - key: readability-identifier-naming.InlineNamespaceIgnoredRegexp 124 | value: '' 125 | - key: readability-identifier-naming.NamespaceIgnoredRegexp 126 | value: '' 127 | - key: google-global-names-in-headers.HeaderFileExtensions 128 | value: ';h;hh;hpp;hxx' 129 | - key: readability-identifier-naming.ClassMemberIgnoredRegexp 130 | value: '' 131 | - key: readability-uppercase-literal-suffix.IgnoreMacros 132 | value: 'true' 133 | - key: modernize-make-shared.IgnoreMacros 134 | value: 'true' 135 | - key: readability-identifier-naming.ClassMethodPrefix 136 | value: '' 137 | - key: readability-identifier-naming.UnionCase 138 | value: CamelCase 139 | - key: performance-unnecessary-copy-initialization.AllowedTypes 140 | value: '' 141 | - key: readability-identifier-naming.GlobalConstantPrefix 142 | value: '' 143 | - key: readability-identifier-naming.ClassMethodIgnoredRegexp 144 | value: '' 145 | - key: readability-suspicious-call-argument.Levenshtein 146 | value: 'true' 147 | - key: readability-identifier-naming.GlobalFunctionSuffix 148 | value: '' 149 | - key: modernize-use-transparent-functors.SafeMode 150 | value: 'false' 151 | - key: readability-identifier-naming.ValueTemplateParameterPrefix 152 | value: '' 153 | - key: readability-identifier-naming.GlobalPointerPrefix 154 | value: '' 155 | - key: readability-identifier-naming.PrivateMethodSuffix 156 | value: '' 157 | - key: readability-identifier-naming.TemplateParameterSuffix 158 | value: '' 159 | - key: readability-identifier-naming.GlobalFunctionCase 160 | value: lower_case 161 | - key: readability-simplify-boolean-expr.ChainedConditionalAssignment 162 | value: 'false' 163 | - key: readability-identifier-naming.ParameterPackSuffix 164 | value: '' 165 | - key: readability-identifier-naming.ConstantPrefix 166 | value: '' 167 | - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField 168 | value: 'false' 169 | - key: readability-function-size.LineThreshold 170 | value: '4294967295' 171 | - key: performance-inefficient-vector-operation.EnableProto 172 | value: 'false' 173 | - key: modernize-use-override.IgnoreDestructors 174 | value: 'false' 175 | - key: modernize-loop-convert.MaxCopySize 176 | value: '16' 177 | - key: readability-suspicious-call-argument.PrefixDissimilarBelow 178 | value: '25' 179 | - key: modernize-make-shared.MakeSmartPtrFunction 180 | value: 'std::make_shared' 181 | - key: readability-identifier-naming.StaticConstantPrefix 182 | value: '' 183 | - key: portability-simd-intrinsics.Suggest 184 | value: 'false' 185 | - key: readability-identifier-naming.ClassConstantCase 186 | value: lower_case 187 | - key: readability-identifier-naming.PrivateMemberPrefix 188 | value: '' 189 | - key: modernize-make-shared.MakeSmartPtrFunctionHeader 190 | value: '' 191 | - key: readability-identifier-naming.PublicMethodCase 192 | value: lower_case 193 | - key: readability-identifier-naming.ProtectedMethodCase 194 | value: lower_case 195 | - key: readability-identifier-naming.InlineNamespaceCase 196 | value: lower_case 197 | - key: readability-identifier-naming.LocalConstantPointerIgnoredRegexp 198 | value: '' 199 | - key: readability-identifier-naming.FunctionSuffix 200 | value: '' 201 | - key: readability-redundant-string-init.StringNames 202 | value: '::std::basic_string_view;::std::basic_string' 203 | - key: modernize-make-unique.IgnoreDefaultInitialization 204 | value: 'true' 205 | - key: modernize-use-emplace.ContainersWithPushBack 206 | value: '::std::vector;::std::list;::std::deque' 207 | - key: readability-magic-numbers.IgnoreBitFieldsWidths 208 | value: 'true' 209 | - key: readability-identifier-naming.PublicMemberSuffix 210 | value: '' 211 | - key: modernize-make-unique.IncludeStyle 212 | value: llvm 213 | - key: modernize-use-override.OverrideSpelling 214 | value: override 215 | - key: google-readability-function-size.NestingThreshold 216 | value: '4294967295' 217 | - key: readability-identifier-naming.PublicMemberCase 218 | value: lower_case 219 | - key: readability-suspicious-call-argument.LevenshteinDissimilarBelow 220 | value: '50' 221 | - key: readability-identifier-naming.ParameterPackIgnoredRegexp 222 | value: '' 223 | - key: readability-identifier-naming.StructSuffix 224 | value: '' 225 | - key: google-readability-braces-around-statements.ShortStatementLines 226 | value: '1' 227 | - key: readability-identifier-naming.ParameterCase 228 | value: lower_case 229 | - key: readability-identifier-naming.ProtectedMemberCase 230 | value: lower_case 231 | - key: readability-identifier-naming.LocalPointerIgnoredRegexp 232 | value: '' 233 | - key: readability-identifier-naming.AbstractClassSuffix 234 | value: '' 235 | - key: readability-identifier-naming.TypeAliasSuffix 236 | value: '' 237 | - key: modernize-use-emplace.IgnoreImplicitConstructors 238 | value: 'false' 239 | - key: google-build-namespaces.HeaderFileExtensions 240 | value: ';h;hh;hpp;hxx' 241 | - key: readability-identifier-naming.TypedefIgnoredRegexp 242 | value: '' 243 | - key: readability-identifier-naming.GlobalFunctionPrefix 244 | value: '' 245 | - key: readability-identifier-naming.LocalVariableSuffix 246 | value: '' 247 | - key: readability-suspicious-call-argument.Substring 248 | value: 'true' 249 | - key: modernize-use-equals-delete.IgnoreMacros 250 | value: 'true' 251 | - key: readability-identifier-naming.ClassIgnoredRegexp 252 | value: '' 253 | - key: readability-identifier-naming.GlobalFunctionIgnoredRegexp 254 | value: '' 255 | - key: readability-magic-numbers.IgnoreAllFloatingPointValues 256 | value: 'false' 257 | - key: readability-identifier-naming.TemplateParameterPrefix 258 | value: '' 259 | - key: readability-identifier-naming.PrivateMethodPrefix 260 | value: '' 261 | - key: readability-identifier-naming.ParameterPackPrefix 262 | value: '' 263 | - key: readability-suspicious-call-argument.Abbreviations 264 | value: 'arr=array;cnt=count;idx=index;src=source;stmt=statement;cpy=copy;dest=destination;dist=distancedst=distance;ptr=pointer;wdth=width;str=string;ln=line;srv=server;attr=attribute;buf=buffer;col=column;vec=vector;nr=number;len=length;elem=element;val=value;ref=reference;i=index;var=variable;hght=height;cl=client;num=number;pos=position;lst=list;addr=address' 265 | - key: readability-uppercase-literal-suffix.NewSuffixes 266 | value: '' 267 | - key: modernize-loop-convert.MinConfidence 268 | value: reasonable 269 | - key: performance-unnecessary-value-param.AllowedTypes 270 | value: '' 271 | - key: readability-uniqueptr-delete-release.PreferResetCall 272 | value: 'false' 273 | - key: readability-identifier-naming.ClassConstantSuffix 274 | value: _ 275 | - key: readability-identifier-naming.FunctionPrefix 276 | value: '' 277 | - key: google-readability-namespace-comments.SpacesBeforeComments 278 | value: '2' 279 | - key: readability-else-after-return.WarnOnUnfixable 280 | value: 'true' 281 | - key: readability-identifier-naming.PublicMethodSuffix 282 | value: '' 283 | - key: readability-identifier-naming.MethodCase 284 | value: lower_case 285 | - key: readability-function-size.BranchThreshold 286 | value: '4294967295' 287 | - key: readability-identifier-naming.FunctionCase 288 | value: lower_case 289 | - key: readability-identifier-naming.ConstexprFunctionIgnoredRegexp 290 | value: '' 291 | - key: readability-implicit-bool-conversion.AllowIntegerConditions 292 | value: 'false' 293 | - key: readability-identifier-naming.PublicMemberPrefix 294 | value: '' 295 | - key: readability-function-size.StatementThreshold 296 | value: '800' 297 | - key: readability-identifier-naming.ConstantParameterCase 298 | value: lower_case 299 | - key: readability-identifier-naming.LocalPointerCase 300 | value: lower_case 301 | - key: readability-identifier-naming.ConstexprFunctionCase 302 | value: lower_case 303 | - key: readability-identifier-naming.PublicMemberIgnoredRegexp 304 | value: '' 305 | - key: readability-identifier-naming.IgnoreMainLikeFunctions 306 | value: 'false' 307 | - key: google-runtime-int.SignedTypePrefix 308 | value: int 309 | - key: google-readability-function-size.StatementThreshold 310 | value: '800' 311 | - key: readability-identifier-naming.ClassConstantIgnoredRegexp 312 | value: '' 313 | - key: readability-identifier-naming.MemberCase 314 | value: lower_case 315 | - key: readability-identifier-naming.StructPrefix 316 | value: '' 317 | - key: readability-identifier-naming.AbstractClassPrefix 318 | value: '' 319 | - key: readability-suspicious-call-argument.DiceSimilarAbove 320 | value: '70' 321 | - key: readability-identifier-naming.TypeAliasPrefix 322 | value: '' 323 | - key: readability-identifier-naming.VirtualMethodIgnoredRegexp 324 | value: '' 325 | - key: readability-suspicious-call-argument.Abbreviation 326 | value: 'true' 327 | - key: readability-identifier-naming.UnionIgnoredRegexp 328 | value: '' 329 | - key: readability-identifier-naming.UnionSuffix 330 | value: '' 331 | - key: readability-identifier-naming.LocalVariablePrefix 332 | value: '' 333 | - key: readability-identifier-naming.NamespaceSuffix 334 | value: '' 335 | - key: modernize-use-equals-default.IgnoreMacros 336 | value: 'true' 337 | - key: modernize-use-emplace.SmartPointers 338 | value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' 339 | - key: readability-identifier-naming.PublicMethodIgnoredRegexp 340 | value: '' 341 | - key: readability-magic-numbers.IgnorePowersOf2IntegerValues 342 | value: 'false' 343 | - key: readability-suspicious-call-argument.JaroWinklerSimilarAbove 344 | value: '85' 345 | - key: readability-identifier-naming.PublicMethodPrefix 346 | value: '' 347 | - key: readability-identifier-naming.ClassConstantPrefix 348 | value: '' 349 | - key: readability-simplify-subscript-expr.Types 350 | value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' 351 | - key: performance-unnecessary-copy-initialization.ExcludedContainerTypes 352 | value: '' 353 | - key: modernize-replace-auto-ptr.IncludeStyle 354 | value: llvm 355 | - key: performance-move-const-arg.CheckTriviallyCopyableMove 356 | value: 'false' 357 | - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold 358 | value: '3' 359 | - key: readability-function-size.VariableThreshold 360 | value: '4294967295' 361 | - key: readability-identifier-naming.VariableIgnoredRegexp 362 | value: '' 363 | - key: readability-identifier-naming.TemplateParameterCase 364 | value: CamelCase 365 | - key: cert-dcl16-c.NewSuffixes 366 | value: 'L;LL;LU;LLU' 367 | - key: readability-identifier-naming.GetConfigPerFile 368 | value: 'true' 369 | - key: readability-identifier-naming.PointerParameterCase 370 | value: lower_case 371 | - key: modernize-use-default-member-init.UseAssignment 372 | value: 'false' 373 | - key: readability-identifier-naming.PrivateMemberIgnoredRegexp 374 | value: '' 375 | - key: readability-function-size.NestingThreshold 376 | value: '4294967295' 377 | - key: google-readability-function-size.BranchThreshold 378 | value: '4294967295' 379 | - key: readability-identifier-naming.MemberSuffix 380 | value: '' 381 | - key: readability-identifier-naming.ValueTemplateParameterIgnoredRegexp 382 | value: '' 383 | - key: readability-identifier-naming.PrivateMethodIgnoredRegexp 384 | value: '' 385 | - key: modernize-use-override.AllowOverrideAndFinal 386 | value: 'false' 387 | - key: readability-function-size.ParameterThreshold 388 | value: '4294967295' 389 | - key: readability-identifier-naming.TypeTemplateParameterSuffix 390 | value: '' 391 | - key: readability-function-cognitive-complexity.IgnoreMacros 392 | value: 'false' 393 | - key: modernize-loop-convert.IncludeStyle 394 | value: llvm 395 | - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons 396 | value: 'false' 397 | - key: readability-identifier-naming.StructIgnoredRegexp 398 | value: '' 399 | - key: readability-identifier-naming.ParameterSuffix 400 | value: '' 401 | - key: readability-identifier-naming.AggressiveDependentMemberLookup 402 | value: 'false' 403 | - key: readability-redundant-smartptr-get.IgnoreMacros 404 | value: 'true' 405 | - key: google-readability-function-size.ParameterThreshold 406 | value: '4294967295' 407 | - key: readability-identifier-naming.UnionPrefix 408 | value: '' 409 | - key: readability-identifier-naming.ConstantIgnoredRegexp 410 | value: '' 411 | - key: readability-identifier-naming.NamespacePrefix 412 | value: '' 413 | - key: readability-identifier-naming.ConstexprVariableSuffix 414 | value: '' 415 | - key: readability-identifier-naming.ConstantPointerParameterSuffix 416 | value: '' 417 | - key: readability-identifier-naming.TypeTemplateParameterCase 418 | value: CamelCase 419 | - key: readability-identifier-naming.StructCase 420 | value: lower_case 421 | - key: modernize-use-emplace.TupleTypes 422 | value: '::std::pair;::std::tuple' 423 | - key: modernize-use-emplace.TupleMakeFunctions 424 | value: '::std::make_pair;::std::make_tuple' 425 | - key: readability-identifier-naming.LocalConstantPointerSuffix 426 | value: '' 427 | - key: readability-identifier-naming.TypedefCase 428 | value: lower_case 429 | - key: modernize-replace-random-shuffle.IncludeStyle 430 | value: llvm 431 | - key: modernize-use-bool-literals.IgnoreMacros 432 | value: 'true' 433 | - key: readability-identifier-naming.ProtectedMemberIgnoredRegexp 434 | value: '' 435 | - key: readability-identifier-naming.GlobalConstantCase 436 | value: lower_case 437 | - key: google-readability-namespace-comments.ShortNamespaceLines 438 | value: '10' 439 | - key: readability-suspicious-call-argument.JaroWinklerDissimilarBelow 440 | value: '75' 441 | - key: modernize-avoid-bind.PermissiveParameterList 442 | value: 'false' 443 | - key: readability-identifier-naming.PrivateMethodCase 444 | value: lower_case 445 | - key: readability-suspicious-call-argument.Suffix 446 | value: 'true' 447 | - key: readability-identifier-naming.ConstexprMethodSuffix 448 | value: '' 449 | - key: readability-identifier-naming.ConstantMemberCase 450 | value: lower_case 451 | - key: readability-identifier-naming.ProtectedMethodIgnoredRegexp 452 | value: '' 453 | - key: readability-identifier-naming.MethodSuffix 454 | value: '' 455 | - key: modernize-use-noexcept.ReplacementString 456 | value: '' 457 | - key: modernize-use-using.IgnoreMacros 458 | value: 'true' 459 | - key: readability-identifier-naming.ConstexprMethodCase 460 | value: lower_case 461 | - key: readability-identifier-naming.TypeAliasIgnoredRegexp 462 | value: '' 463 | - key: readability-identifier-naming.MemberPrefix 464 | value: '' 465 | - key: readability-suspicious-call-argument.MinimumIdentifierNameLength 466 | value: '3' 467 | - key: readability-identifier-naming.LocalConstantSuffix 468 | value: '' 469 | - key: readability-identifier-naming.ClassSuffix 470 | value: '' 471 | - key: modernize-loop-convert.NamingStyle 472 | value: CamelCase 473 | - key: readability-identifier-naming.TypeTemplateParameterPrefix 474 | value: '' 475 | - key: readability-identifier-naming.PrivateMemberCase 476 | value: lower_case 477 | - key: performance-no-automatic-move.AllowedTypes 478 | value: '' 479 | - key: readability-suspicious-call-argument.SubstringDissimilarBelow 480 | value: '40' 481 | - key: google-runtime-int.UnsignedTypePrefix 482 | value: uint 483 | - key: readability-identifier-naming.EnumConstantIgnoredRegexp 484 | value: '' 485 | - key: performance-for-range-copy.WarnOnAllAutoCopies 486 | value: 'false' 487 | - key: readability-identifier-naming.ParameterPrefix 488 | value: '' 489 | - key: readability-identifier-naming.TemplateTemplateParameterCase 490 | value: CamelCase 491 | - key: modernize-pass-by-value.IncludeStyle 492 | value: llvm 493 | - key: readability-identifier-naming.ProtectedMemberSuffix 494 | value: _ 495 | - key: readability-identifier-naming.ConstexprVariablePrefix 496 | value: '' 497 | - key: readability-identifier-naming.GlobalConstantPointerSuffix 498 | value: '' 499 | - key: readability-simplify-boolean-expr.ChainedConditionalReturn 500 | value: 'false' 501 | - key: readability-identifier-naming.ConstantPointerParameterPrefix 502 | value: '' 503 | - key: modernize-use-override.FinalSpelling 504 | value: final 505 | - key: readability-else-after-return.WarnOnConditionVariables 506 | value: 'true' 507 | - key: modernize-use-nullptr.NullMacros 508 | value: 'NULL' 509 | - key: readability-suspicious-call-argument.SuffixDissimilarBelow 510 | value: '25' 511 | - key: readability-identifier-naming.LocalConstantPointerPrefix 512 | value: '' 513 | - key: readability-suspicious-call-argument.LevenshteinSimilarAbove 514 | value: '66' 515 | - key: readability-identifier-naming.NamespaceCase 516 | value: lower_case 517 | - key: modernize-make-shared.IgnoreDefaultInitialization 518 | value: 'true' 519 | - key: readability-suspicious-call-argument.JaroWinkler 520 | value: 'true' 521 | - key: readability-identifier-naming.GlobalPointerCase 522 | value: lower_case 523 | - key: modernize-make-shared.IncludeStyle 524 | value: llvm 525 | - key: readability-identifier-naming.LocalConstantPointerCase 526 | value: lower_case 527 | - key: readability-suspicious-call-argument.Prefix 528 | value: 'true' 529 | - key: readability-identifier-naming.ConstexprMethodPrefix 530 | value: '' 531 | - key: readability-identifier-naming.ValueTemplateParameterCase 532 | value: CamelCase 533 | - key: readability-identifier-naming.MethodPrefix 534 | value: '' 535 | - key: readability-identifier-naming.ConstexprMethodIgnoredRegexp 536 | value: '' 537 | - key: readability-identifier-naming.AbstractClassIgnoredRegexp 538 | value: '' 539 | - key: readability-identifier-naming.ConstantParameterIgnoredRegexp 540 | value: '' 541 | - key: readability-identifier-naming.ProtectedMethodSuffix 542 | value: '' 543 | - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors 544 | value: 'true' 545 | - key: readability-identifier-naming.LocalConstantPrefix 546 | value: '' 547 | - key: modernize-make-unique.IgnoreMacros 548 | value: 'true' 549 | - key: readability-identifier-naming.ConstantCase 550 | value: lower_case 551 | - key: performance-for-range-copy.AllowedTypes 552 | value: '' 553 | - key: readability-identifier-naming.ClassPrefix 554 | value: '' 555 | - key: readability-identifier-naming.GlobalConstantPointerPrefix 556 | value: '' 557 | - key: readability-identifier-naming.GlobalVariableSuffix 558 | value: '' 559 | - key: readability-identifier-naming.StaticConstantCase 560 | value: lower_case 561 | - key: readability-identifier-naming.ProtectedMemberPrefix 562 | value: '' 563 | - key: readability-identifier-naming.ClassCase 564 | value: lower_case 565 | - key: readability-identifier-naming.GlobalVariableCase 566 | value: lower_case 567 | - key: readability-identifier-naming.PointerParameterIgnoredRegexp 568 | value: '' 569 | - key: readability-magic-numbers.IgnoredFloatingPointValues 570 | value: '1.0;100.0;' 571 | - key: performance-inefficient-string-concatenation.StrictMode 572 | value: 'false' 573 | - key: readability-implicit-bool-conversion.AllowPointerConditions 574 | value: 'false' 575 | - key: readability-identifier-naming.VirtualMethodCase 576 | value: lower_case 577 | - key: readability-identifier-naming.VariableSuffix 578 | value: '' 579 | - key: modernize-make-unique.MakeSmartPtrFunction 580 | value: 'std::make_unique' 581 | - key: google-runtime-int.TypeSuffix 582 | value: '' 583 | - key: portability-restrict-system-includes.Includes 584 | value: '*' 585 | - key: readability-identifier-naming.StaticVariableSuffix 586 | value: '' 587 | - key: readability-identifier-naming.LocalVariableIgnoredRegexp 588 | value: '' 589 | - key: modernize-make-unique.MakeSmartPtrFunctionHeader 590 | value: '' 591 | - key: readability-suspicious-call-argument.SubstringSimilarAbove 592 | value: '50' 593 | - key: readability-identifier-naming.TypedefSuffix 594 | value: '' 595 | - key: readability-identifier-naming.EnumSuffix 596 | value: '' 597 | - key: readability-identifier-naming.PointerParameterSuffix 598 | value: '' 599 | - key: modernize-use-noexcept.UseNoexceptFalse 600 | value: 'true' 601 | - key: readability-function-cognitive-complexity.Threshold 602 | value: '25' 603 | - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic 604 | value: 'true' 605 | - key: readability-identifier-naming.ProtectedMethodPrefix 606 | value: '' 607 | - key: readability-identifier-naming.VirtualMethodSuffix 608 | value: '' 609 | - key: performance-faster-string-find.StringLikeClasses 610 | value: '::std::basic_string;::std::basic_string_view' 611 | - key: readability-identifier-naming.ConstexprVariableIgnoredRegexp 612 | value: '' 613 | - key: google-readability-function-size.VariableThreshold 614 | value: '4294967295' 615 | - key: readability-identifier-naming.InlineNamespaceSuffix 616 | value: '' 617 | - key: readability-identifier-naming.ConstantParameterSuffix 618 | value: '' 619 | - key: readability-identifier-naming.GlobalVariablePrefix 620 | value: '' 621 | - key: modernize-use-default-member-init.IgnoreMacros 622 | value: 'true' 623 | - key: llvm-qualified-auto.AddConstToQualified 624 | value: 'false' 625 | - key: readability-identifier-naming.LocalConstantIgnoredRegexp 626 | value: '' 627 | - key: readability-identifier-naming.GlobalVariableIgnoredRegexp 628 | value: '' 629 | - key: readability-identifier-naming.TemplateTemplateParameterIgnoredRegexp 630 | value: '' 631 | - key: readability-identifier-naming.ConstantPointerParameterIgnoredRegexp 632 | value: '' 633 | - key: readability-identifier-naming.TemplateTemplateParameterSuffix 634 | value: '' 635 | - key: llvm-else-after-return.WarnOnConditionVariables 636 | value: 'false' 637 | - key: readability-identifier-naming.LocalConstantCase 638 | value: lower_case 639 | - key: readability-identifier-naming.VariablePrefix 640 | value: '' 641 | - key: readability-identifier-naming.ConstantMemberIgnoredRegexp 642 | value: '' 643 | - key: modernize-raw-string-literal.DelimiterStem 644 | value: lit 645 | - key: readability-identifier-naming.FunctionIgnoredRegexp 646 | value: '' 647 | - key: readability-suspicious-call-argument.Dice 648 | value: 'true' 649 | - key: readability-identifier-naming.StaticVariablePrefix 650 | value: '' 651 | - key: readability-identifier-naming.TypedefPrefix 652 | value: '' 653 | - key: readability-identifier-naming.VariableCase 654 | value: lower_case 655 | - key: readability-identifier-naming.EnumPrefix 656 | value: '' 657 | - key: modernize-raw-string-literal.ReplaceShorterLiterals 658 | value: 'false' 659 | - key: readability-identifier-naming.AbstractClassCase 660 | value: lower_case 661 | - key: performance-inefficient-vector-operation.VectorLikeClasses 662 | value: '::std::vector' 663 | - key: readability-identifier-naming.ConstexprVariableCase 664 | value: lower_case 665 | - key: readability-magic-numbers.IgnoredIntegerValues 666 | value: '1;2;3;4;' 667 | - key: modernize-use-auto.RemoveStars 668 | value: 'false' 669 | - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors 670 | value: 'false' 671 | - key: performance-unnecessary-value-param.IncludeStyle 672 | value: llvm 673 | - key: portability-simd-intrinsics.Std 674 | value: '' 675 | - key: readability-identifier-naming.ConstantPointerParameterCase 676 | value: lower_case 677 | - key: llvm-else-after-return.WarnOnUnfixable 678 | value: 'false' 679 | - key: readability-identifier-naming.TemplateParameterIgnoredRegexp 680 | value: '' 681 | ... 682 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf encoding=utf-8 2 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - main 9 | tags: 10 | - "v*" 11 | 12 | concurrency: 13 | group: test-${{ github.ref }} 14 | cancel-in-progress: false 15 | 16 | jobs: 17 | windows-build: 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | compiler: [{ c: "clang-cl", cxx: "clang-cl" }, { c: "cl", cxx: "cl" }] 22 | name: Windows - ${{ matrix.compiler.cxx }} 23 | runs-on: windows-latest 24 | 25 | env: 26 | triplet: x64-windows 27 | 28 | steps: 29 | - uses: actions/checkout@v4 30 | with: 31 | submodules: true 32 | 33 | - name: Configure VS Toolchain 34 | uses: ilammy/msvc-dev-cmd@v1 35 | 36 | - name: Install dependencies 37 | run: vcpkg install gtest --triplet ${{ env.triplet }} 38 | 39 | - name: Build and test 40 | run: | 41 | rm -rf "${{ github.workspace }}\build" 42 | cmake -B "${{ github.workspace }}\build" -DCMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT\\scripts\\buildsystems\\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 43 | # cmake --build "${{ github.workspace }}\build" --config Debug --clean-first 44 | # ctest --test-dir "${{ github.workspace }}\build" -C Debug 45 | cmake --build "${{ github.workspace }}\build" --config Release --clean-first 46 | ctest --test-dir "${{ github.workspace }}\build" -C Release 47 | shell: bash 48 | 49 | ubuntu2204-build: 50 | strategy: 51 | fail-fast: false 52 | matrix: 53 | compiler: 54 | [ 55 | { c: "gcc-11", cxx: "g++-11" }, 56 | ] 57 | name: Ubuntu - ${{ matrix.compiler.cxx }} 58 | runs-on: ubuntu-22.04 59 | 60 | env: 61 | triplet: x64-linux 62 | 63 | steps: 64 | - uses: actions/checkout@v4 65 | with: 66 | submodules: true 67 | 68 | - name: Install compilers 69 | run: | 70 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 71 | brew install ninja 72 | 73 | - name: Install dependencies 74 | run: vcpkg install gtest --triplet ${{ env.triplet }} 75 | 76 | - name: Build and test 77 | run: | 78 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 79 | rm -rf ${{ github.workspace }}/build 80 | cmake -B ${{ github.workspace }}/build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 81 | cmake --build ${{ github.workspace }}/build --config Debug --clean-first 82 | ctest --test-dir ${{ github.workspace }}/build -C Debug 83 | cmake --build ${{ github.workspace }}/build --config Release --clean-first 84 | ctest --test-dir ${{ github.workspace }}/build -C Release 85 | 86 | ubuntu2404-build: 87 | strategy: 88 | fail-fast: false 89 | matrix: 90 | compiler: 91 | [ 92 | { c: "gcc-12", cxx: "g++-12" }, 93 | { c: "gcc-13", cxx: "g++-13" }, 94 | { c: "gcc-14", cxx: "g++-14" }, 95 | { 96 | c: "$(brew --prefix llvm@15)/bin/clang", 97 | cxx: "$(brew --prefix llvm@15)/bin/clang++", 98 | }, 99 | { 100 | c: "$(brew --prefix llvm@16)/bin/clang", 101 | cxx: "$(brew --prefix llvm@16)/bin/clang++", 102 | }, 103 | { 104 | c: "$(brew --prefix llvm@17)/bin/clang", 105 | cxx: "$(brew --prefix llvm@17)/bin/clang++", 106 | }, 107 | { 108 | c: "$(brew --prefix llvm@18)/bin/clang", 109 | cxx: "$(brew --prefix llvm@18)/bin/clang++", 110 | }, 111 | { 112 | c: "$(brew --prefix llvm@19)/bin/clang", 113 | cxx: "$(brew --prefix llvm@19)/bin/clang++", 114 | }, 115 | ] 116 | name: Ubuntu - ${{ matrix.compiler.cxx }} 117 | runs-on: ubuntu-24.04 118 | 119 | env: 120 | triplet: x64-linux 121 | 122 | steps: 123 | - uses: actions/checkout@v4 124 | with: 125 | submodules: true 126 | 127 | - name: Install compilers 128 | run: | 129 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 130 | brew install ninja llvm@15 llvm@16 llvm@17 llvm@18 llvm@19 131 | 132 | - name: Install dependencies 133 | run: vcpkg install gtest --triplet ${{ env.triplet }} 134 | 135 | - name: Build and test 136 | run: | 137 | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" 138 | rm -rf ${{ github.workspace }}/build 139 | cmake -B ${{ github.workspace }}/build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 140 | cmake --build ${{ github.workspace }}/build --config Debug --clean-first 141 | ctest --test-dir ${{ github.workspace }}/build -C Debug 142 | cmake --build ${{ github.workspace }}/build --config Release --clean-first 143 | ctest --test-dir ${{ github.workspace }}/build -C Release 144 | 145 | macos-build: 146 | strategy: 147 | fail-fast: false 148 | matrix: 149 | compiler: 150 | [ 151 | { c: "gcc-12", cxx: "g++-12" }, 152 | { c: "gcc-13", cxx: "g++-13" }, 153 | { c: "gcc-14", cxx: "g++-14" }, 154 | { 155 | c: "$(brew --prefix llvm@16)/bin/clang", 156 | cxx: "$(brew --prefix llvm@16)/bin/clang++", 157 | }, 158 | { 159 | c: "$(brew --prefix llvm@17)/bin/clang", 160 | cxx: "$(brew --prefix llvm@17)/bin/clang++", 161 | }, 162 | { 163 | c: "$(brew --prefix llvm@18)/bin/clang", 164 | cxx: "$(brew --prefix llvm@18)/bin/clang++", 165 | }, 166 | { 167 | c: "$(brew --prefix llvm@19)/bin/clang", 168 | cxx: "$(brew --prefix llvm@19)/bin/clang++", 169 | }, 170 | ] 171 | name: MacOS - ${{ matrix.compiler.cxx }} 172 | runs-on: macos-latest 173 | 174 | env: 175 | triplet: arm64-osx 176 | 177 | steps: 178 | - uses: actions/checkout@v4 179 | with: 180 | submodules: true 181 | 182 | - name: Install compilers 183 | run: brew install ninja llvm@16 llvm@17 llvm@18 llvm@19 184 | 185 | - name: Install dependencies 186 | run: | 187 | git clone --depth=1 https://github.com/microsoft/vcpkg.git 188 | ./vcpkg/bootstrap-vcpkg.sh 189 | CC=${{ matrix.compiler.c }} CXX=${{ matrix.compiler.cxx }} ./vcpkg/vcpkg install gtest --triplet ${{ env.triplet }} 190 | 191 | - name: Build and test 192 | run: | 193 | rm -rf ${{ github.workspace }}/build 194 | cmake -B ${{ github.workspace }}/build -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} -G "Ninja Multi-Config" 195 | cmake --build ${{ github.workspace }}/build --config Debug --clean-first 196 | ctest --test-dir ${{ github.workspace }}/build -C Debug 197 | cmake --build ${{ github.workspace }}/build --config Release --clean-first 198 | ctest --test-dir ${{ github.workspace }}/build -C Release 199 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # CMake 35 | CMakeLists.txt.user 36 | CMakeCache.txt 37 | CMakeFiles 38 | CMakeScripts 39 | Testing 40 | Makefile 41 | cmake_install.cmake 42 | install_manifest.txt 43 | compile_commands.json 44 | CTestTestfile.cmake 45 | _deps 46 | 47 | # build directory 48 | build/ 49 | 50 | # etc 51 | **/.vs/ 52 | **/.vscode/ 53 | **/.ccls-cache/ 54 | **/.clangd/ 55 | **/.cache/ 56 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project( 3 | field_reflection 4 | VERSION 0.2.1 5 | LANGUAGES CXX) 6 | 7 | # check if the project is top-level 8 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) 9 | set(FIELD_RFL_IS_TOPLEVEL_PROJECT ON) 10 | else() 11 | set(FIELD_RFL_IS_TOPLEVEL_PROJECT OFF) 12 | endif() 13 | 14 | # options 15 | option(FIELD_RFL_BUILD_TEST "Build ${PROJECT_NAME} tests" 16 | ${FIELD_RFL_IS_TOPLEVEL_PROJECT}) 17 | 18 | # library 19 | include(GNUInstallDirs) 20 | add_library(${PROJECT_NAME} INTERFACE) 21 | add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) 22 | target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20) 23 | target_include_directories( 24 | ${PROJECT_NAME} 25 | INTERFACE $ 26 | $) 27 | set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION}) 28 | 29 | # for MSVC 30 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 31 | target_compile_options(${PROJECT_NAME} INTERFACE /Zc:preprocessor) 32 | endif() 33 | 34 | # install 35 | if(FIELD_RFL_IS_TOPLEVEL_PROJECT) 36 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}_Targets) 37 | 38 | install( 39 | EXPORT ${PROJECT_NAME}_Targets 40 | FILE ${PROJECT_NAME}Targets.cmake 41 | NAMESPACE ${PROJECT_NAME}:: 42 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 43 | 44 | include(CMakePackageConfigHelpers) 45 | write_basic_package_version_file( 46 | ${PROJECT_NAME}ConfigVersion.cmake COMPATIBILITY SameMajorVersion 47 | ARCH_INDEPENDENT) 48 | configure_package_config_file( 49 | "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" 50 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 51 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 52 | 53 | # install config files 54 | install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 55 | "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 56 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) 57 | 58 | # install header files 59 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ 60 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 61 | endif() 62 | 63 | # test 64 | if(FIELD_RFL_BUILD_TEST) 65 | enable_testing() 66 | add_subdirectory(test) 67 | endif() 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Yoshiki Matsuda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # field-reflection C++ 2 | 3 | Compile-time reflection for C++ to get field names and types from a struct/class. 4 | 5 | [![CI](https://github.com/yosh-matsuda/field-reflection/actions/workflows/tests.yml/badge.svg)](https://github.com/yosh-matsuda/field-reflection/actions/workflows/tests.yml) 6 | 7 | ## Features 8 | 9 | * compile-time reflection 10 | * header-only single file 11 | * no user-side macros 12 | * no dependencies 13 | 14 | ## Requirements 15 | 16 | C++20 compilers are required to use this library. 17 | 18 | * GCC >= 11 19 | * Clang >= 15 20 | * with libc++-16 or later 21 | * MSVC >= 19.37 22 | * clang-cl >= 17 23 | 24 | ## Usage 25 | 26 | ```cpp 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "field_reflection.hpp" 33 | 34 | using namespace field_reflection; 35 | 36 | struct my_struct 37 | { 38 | int i = 287; 39 | double d = 3.14; 40 | std::string hello = "Hello World"; 41 | std::array arr = {1, 2, 3}; 42 | std::map map{{"one", 1}, {"two", 2}}; 43 | }; 44 | 45 | // get field names 46 | constexpr auto my_struct_n0 = field_name; // "i"sv 47 | constexpr auto my_struct_n1 = field_name; // "d"sv 48 | constexpr auto my_struct_n2 = field_name; // "hello"sv 49 | constexpr auto my_struct_n3 = field_name; // "arr"sv 50 | constexpr auto my_struct_n4 = field_name; // "map"sv 51 | 52 | // get field types 53 | using my_struct_t0 = field_type; // int 54 | using my_struct_t1 = field_type; // double 55 | using my_struct_t2 = field_type; // std::string 56 | using my_struct_t3 = field_type; // std::array 57 | using my_struct_t4 = field_type; // std::map 58 | 59 | // get field values with index 60 | auto s = my_struct{}; 61 | auto& my_struct_v0 = get_field<0>(s); // s.i 62 | auto& my_struct_v1 = get_field<1>(s); // s.d 63 | auto& my_struct_v2 = get_field<2>(s); // s.hello 64 | auto& my_struct_v3 = get_field<3>(s); // s.arr 65 | auto& my_struct_v4 = get_field<4>(s); // s.map 66 | 67 | // visit each field 68 | for_each_field(s, [](std::string_view field, auto& value) { 69 | // i: 287 70 | // d: 3.14 71 | // hello: Hello World 72 | // arr: [1, 2, 3] 73 | // map: {"one": 1, "two": 2} 74 | std::println("{}: {}", field, value); 75 | }); 76 | ``` 77 | 78 | ## API References 79 | 80 | ### Concepts 81 | 82 | ```cpp 83 | template 84 | concept field_countable; 85 | template 86 | concept field_referenceable; 87 | template 88 | concept field_namable; 89 | ``` 90 | 91 | The `field_countable` is a concept that checks if the type `T` is a field-countable struct. Internally, it is equivalent to that `T` is [aggregate type](https://en.cppreference.com/w/cpp/types/is_aggregate) and the number of the field is less than or equal to `100`. 92 | 93 | The `field_referenceable` is a concept that checks if a field of the type `T` can be referenced by index. This includes the `field_countable` concept. The implementation of the `field_referenceable` concept is the condition that the `field_countable` type `T` has no base class. 94 | 95 | The `field_namable` is a concept that checks if a field name of the type `T` can be obtained by index statically. This includes the `field_referenceable` concept and also requires that the type `T` has a field and (practically) there is no reference type member. 96 | 97 | ### `field_count` 98 | 99 | ```cpp 100 | template 101 | constexpr std::size_t field_count; 102 | ``` 103 | 104 | Get the number of fields from the `field_countable` type `T`. 105 | 106 | ### `field_name` 107 | 108 | ```cpp 109 | template 110 | constexpr std::string_view field_name; 111 | ``` 112 | 113 | Get the name of the `N`-th field as `std::string_view` from the `field_namable` type `T`. 114 | 115 | ### `field_type` 116 | 117 | ```cpp 118 | template 119 | using field_type; 120 | ``` 121 | 122 | Get the type of the `N`-th field from the `field_referenceable` type `T`. 123 | 124 | ### `get_field` 125 | 126 | ```cpp 127 | // reference 128 | template 129 | constexpr auto& get_field(T& t) noexcept; 130 | 131 | // const reference 132 | template 133 | constexpr const auto& get_field(const T& t) noexcept; 134 | 135 | // rvalue reference 136 | template 137 | constexpr auto get_field(T&& t) noexcept; 138 | ``` 139 | 140 | Extracts the `N`-th element from the `field_referenceable` type `T` and returns a reference to it. It behaves like `std::get` for `std::tuple` but returns a lvalue value instead of a rvalue reference. 141 | 142 | ### `type_name` 143 | 144 | ```cpp 145 | template 146 | constexpr std::string_view type_name; 147 | ``` 148 | 149 | Get the name of the type `T`. 150 | 151 |
152 | Example 153 | 154 | ```cpp 155 | #include 156 | #include 157 | #include 158 | #include // std::exchange 159 | #include 160 | 161 | using Token = std::variant; 162 | 163 | struct Number { 164 | int value; 165 | }; 166 | 167 | struct Identifier { 168 | std::string name; 169 | }; 170 | 171 | template 172 | inline constexpr bool alternative_of = false; 173 | 174 | template 175 | inline constexpr bool alternative_of> = 176 | (std::is_same_v || ...); 177 | 178 | template 179 | requires alternative_of 180 | struct std::formatter { 181 | constexpr auto parse(auto& ctx) -> decltype(ctx.begin()) { 182 | auto it = ctx.begin(); 183 | if (it != ctx.end() and *it != '}') { 184 | throw std::format_error("invalid format"); 185 | } 186 | return it; 187 | } 188 | 189 | auto format(const T& t, auto& ctx) const -> decltype(ctx.out()) { 190 | auto out = ctx.out(); 191 | out = std::format_to(out, "{} {{", field_reflection::type_name); 192 | const char* dlm = ""; 193 | field_reflection::for_each_field( 194 | t, [&](std::string_view name, const auto& value) { 195 | std::format_to( 196 | out, "{}\n .{}={}", std::exchange(dlm, ","), name, value); 197 | }); 198 | out = std::format_to(out, "\n}}"); 199 | return out; 200 | } 201 | }; 202 | 203 | #include 204 | 205 | int main() { 206 | Number num{42}; 207 | Identifier ident{"ident"}; 208 | std::cout << std::format("{}", num) << std::endl; 209 | std::cout << std::format("{}", ident) << std::endl; 210 | // Expected Output 211 | // =============== 212 | // Number { 213 | // .value=42 214 | // } 215 | // Identifier { 216 | // .name=ident 217 | // } 218 | } 219 | ``` 220 | 221 | 🔗[Execution example in Compiler Explorer](https://godbolt.org/z/94fPc895o) 222 |
223 | 224 | ### `for_each_field`, `all_of_field`, `any_of_field` 225 | 226 | ```cpp 227 | // unary operation 228 | template 229 | void for_each_field(T&& t, Func&& func); 230 | template 231 | bool all_of_field(T&& t, Func&& func); 232 | template 233 | bool any_of_field(T&& t, Func&& func); 234 | 235 | // binary operation 236 | template 237 | void for_each_field(T&& t1, T&& t2, Func&& func); 238 | template 239 | bool all_of_field(T&& t1, T&& t2, Func&& func); 240 | template 241 | bool any_of_field(T&& t1, T&& t2, Func&& func); 242 | ``` 243 | 244 | Visits each field of the type `T` and applies the unary or binary operation `func`. The `func` must be a callable object that takes one of the following kinds of arguments: 245 | 246 | * Arguments of one or two references to the field for the `field_referenceable` type `T`. 247 | * Arguments of `std::string_view` and one or two references to the field for the `field_namable` type `T`. 248 | 249 | The `for_each_field` just applies the `func` and returns `void`, while the `all_of_field` and `any_of_field` return `bool` indicating whether all or any of the `func` returns `true`. 250 | 251 | For example, the following code prints the field names and values of the `my_struct` `s`: 252 | 253 | ```cpp 254 | constexpr auto func = [](std::string_view field, auto& value) { 255 | std::println("{}: {}", field, value); 256 | }; 257 | for_each_field(s, func); 258 | ``` 259 | 260 | The above is equivalent to: 261 | 262 | ```cpp 263 | func("i"sv, s.i); 264 | func("d"sv, s.d); 265 | func("hello"sv, s.hello); 266 | func("arr"sv, s.arr); 267 | func("map"sv, s.map); 268 | ``` 269 | 270 | The first argument in the definition of the `func` can be omitted if it is not needed. 271 | 272 | The binary operation version of `for_each_field` is useful for comparing each field of two objects of the same type: 273 | 274 | ```cpp 275 | constexpr auto func = [](std::string_view field, auto& value1, auto& value2) { 276 | if (value1 != value2) { 277 | std::println("s1 and s2 have a different value: s1.{} = {}, s2.{} = {}", 278 | field, value1, field, value2); 279 | } 280 | }; 281 | for_each_field(s1, s2, func); 282 | ``` 283 | 284 | ### `to_tuple` 285 | 286 | ```cpp 287 | template 288 | constexpr std::tuple<...> to_tuple(T&& t); 289 | ``` 290 | 291 | Copy a `field_referenceable` type `T` object and convert it to `std::tuple` where each field has the same type as `T`. For example, `my_struct` object can be converted to object of type `std::tuple, std::map>`. 292 | 293 | ## Acknowledgments 294 | 295 | This project is strongly inspired by the following and stands as 296 | 297 | * an alternative to [visit_struct](https://github.com/cbeck88/visit_struct) without macros, 298 | * a reflection library that is a partial reimplementation of [reflect-cpp](https://github.com/getml/reflect-cpp). 299 | 300 | The C++20 implementation of the counting field in this library is partially referenced to [Boost.PFR](https://github.com/boostorg/pfr). 301 | -------------------------------------------------------------------------------- /cmake/field_reflectionConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | set(FIELD_RFL_VERSION @PROJECT_VERSION@) 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") 6 | check_required_components("@PROJECT_NAME@") 7 | -------------------------------------------------------------------------------- /include/field_reflection.hpp: -------------------------------------------------------------------------------- 1 | /*===================================================* 2 | | field-reflection version v0.2.1 | 3 | | https://github.com/yosh-matsuda/field-reflection | 4 | | | 5 | | Copyright (c) 2024 Yoshiki Matsuda @yosh-matsuda | 6 | | | 7 | | This software is released under the MIT License. | 8 | | https://opensource.org/license/mit/ | 9 | ====================================================*/ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include // CHAR_BIT 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace field_reflection 23 | { 24 | namespace detail 25 | { 26 | 27 | #if defined(__GNUC__) || defined(__clang__) 28 | #pragma GCC diagnostic push 29 | #pragma GCC diagnostic ignored "-Wundefined-inline" 30 | #endif 31 | template 32 | struct any_lref 33 | { 34 | template 35 | requires (!std::same_as) 36 | constexpr operator U&() const&& noexcept; // NOLINT 37 | template 38 | requires (!std::same_as) 39 | constexpr operator U&() const& noexcept; // NOLINT 40 | }; 41 | 42 | template 43 | struct any_rref 44 | { 45 | template 46 | requires (!std::same_as) 47 | constexpr operator U() const&& noexcept; // NOLINT 48 | }; 49 | 50 | template 51 | struct any_lref_no_base 52 | { 53 | template 54 | requires (!std::is_base_of_v && !std::same_as) 55 | constexpr operator U&() const&& noexcept; // NOLINT 56 | template 57 | requires (!std::is_base_of_v && !std::same_as) 58 | constexpr operator U&() const& noexcept; // NOLINT 59 | }; 60 | 61 | template 62 | struct any_rref_no_base 63 | { 64 | template 65 | requires (!std::is_base_of_v && !std::same_as) 66 | constexpr operator U() const&& noexcept; // NOLINT 67 | }; 68 | 69 | template 70 | struct any_lref_base 71 | { 72 | template 73 | requires std::is_base_of_v 74 | constexpr operator U&() const&& noexcept; // NOLINT 75 | template 76 | requires std::is_base_of_v 77 | constexpr operator U&() const& noexcept; // NOLINT 78 | }; 79 | 80 | template 81 | struct any_rref_base 82 | { 83 | template 84 | requires std::is_base_of_v 85 | constexpr operator U() const&& noexcept; // NOLINT 86 | }; 87 | #if defined(__GNUC__) || defined(__clang__) 88 | #pragma GCC diagnostic pop 89 | #endif 90 | 91 | template 92 | concept constructible = (ArgNum == 0 && requires { T{}; }) || 93 | [](std::index_sequence) { 94 | if constexpr (std::is_copy_constructible_v) 95 | { 96 | return requires { T{any_lref_no_base(), any_lref()...}; }; 97 | } 98 | else 99 | { 100 | return requires { T{any_rref_no_base(), any_rref()...}; }; 101 | } 102 | }(std::make_index_sequence()); 103 | 104 | template 105 | concept has_base = []() { 106 | if constexpr (std::is_copy_constructible_v) 107 | { 108 | return requires { T{std::declval>()}; }; 109 | } 110 | else 111 | { 112 | return requires { T{std::declval>()}; }; 113 | } 114 | }(); 115 | 116 | constexpr std::size_t macro_max_fields_count = 100; 117 | template 118 | constexpr auto max_field_count = 119 | std::min(std::size_t{macro_max_fields_count}, sizeof(T) * CHAR_BIT); // in consideration of bit field 120 | 121 | template 122 | requires std::is_aggregate_v 123 | constexpr std::size_t field_count_impl = []() { 124 | if constexpr (N >= max_field_count) 125 | { 126 | return std::numeric_limits::max(); 127 | } 128 | else if constexpr (constructible && !constructible) 129 | { 130 | return N; 131 | } 132 | else 133 | { 134 | return field_count_impl; 135 | } 136 | }(); 137 | 138 | template 139 | requires std::is_aggregate_v 140 | constexpr std::size_t field_count_value = field_count_impl; 141 | 142 | template 143 | concept field_countable = 144 | std::is_aggregate_v && requires { requires field_count_value <= max_field_count; }; 145 | 146 | template 147 | constexpr std::size_t field_count = field_count_value; 148 | 149 | template 150 | concept field_referenceable = field_countable && (!has_base); 151 | 152 | template > 153 | constexpr auto to_ptr_tuple(T&&) 154 | { 155 | static_assert([] { return false; }(), "The supported maximum number of fields in struct must be <= 100."); 156 | } 157 | template > 158 | requires (field_count == 0) 159 | constexpr auto to_ptr_tuple(T&&) 160 | { 161 | return std::tie(); 162 | } 163 | template > 164 | requires (field_count == 0) 165 | constexpr auto to_tuple(T&&) 166 | { 167 | return std::tie(); 168 | } 169 | 170 | #pragma region TO_TUPLE_TEMPLATE_MACRO 171 | // map macro: https://github.com/swansontec/map-macro 172 | #define FIELD_RFL_EVAL0(...) __VA_ARGS__ 173 | #define FIELD_RFL_EVAL1(...) FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(__VA_ARGS__))) 174 | #define FIELD_RFL_EVAL2(...) FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(__VA_ARGS__))) 175 | #define FIELD_RFL_EVAL3(...) FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(__VA_ARGS__))) 176 | #define FIELD_RFL_EVAL4(...) FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(__VA_ARGS__))) 177 | #define FIELD_RFL_EVAL(...) FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(__VA_ARGS__))) 178 | 179 | #define FIELD_RFL_MAP_END(...) 180 | #define FIELD_RFL_MAP_OUT 181 | #define FIELD_RFL_MAP_COMMA , 182 | 183 | #define FIELD_RFL_MAP_GET_END2() 0, FIELD_RFL_MAP_END 184 | #define FIELD_RFL_MAP_GET_END1(...) FIELD_RFL_MAP_GET_END2 185 | #define FIELD_RFL_MAP_GET_END(...) FIELD_RFL_MAP_GET_END1 186 | #define FIELD_RFL_MAP_NEXT0(test, next, ...) next FIELD_RFL_MAP_OUT 187 | #define FIELD_RFL_MAP_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, next, 0) 188 | #define FIELD_RFL_MAP_NEXT(test, next) FIELD_RFL_MAP_NEXT1(FIELD_RFL_MAP_GET_END test, next) 189 | 190 | #define FIELD_RFL_MAP0(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP1)(f, peek, __VA_ARGS__) 191 | #define FIELD_RFL_MAP1(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP0)(f, peek, __VA_ARGS__) 192 | 193 | #define FIELD_RFL_MAP_LIST_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, FIELD_RFL_MAP_COMMA next, 0) 194 | #define FIELD_RFL_MAP_LIST_NEXT(test, next) FIELD_RFL_MAP_LIST_NEXT1(FIELD_RFL_MAP_GET_END test, next) 195 | 196 | #define FIELD_RFL_MAP_LIST0(f, x, peek, ...) \ 197 | f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST1)(f, peek, __VA_ARGS__) 198 | #define FIELD_RFL_MAP_LIST1(f, x, peek, ...) \ 199 | f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST0)(f, peek, __VA_ARGS__) 200 | #define FIELD_RFL_MAP(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 201 | #define FIELD_RFL_MAP_LIST(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 202 | 203 | #define FIELD_RFL_ADDR(x) &x 204 | #define FIELD_RFL_DECLTYPE(x) decltype(x) 205 | #define FIELD_RFL_FORWARD(x) std::forward(x) 206 | 207 | #define TO_TUPLE_TEMPLATE(NUM, ...) \ 208 | template > \ 209 | requires (field_count == NUM) \ 210 | constexpr auto to_ptr_tuple(T&& t) \ 211 | { \ 212 | auto& [__VA_ARGS__] = t; \ 213 | return std::tuple(FIELD_RFL_MAP_LIST(FIELD_RFL_ADDR, __VA_ARGS__)); \ 214 | } \ 215 | template > \ 216 | requires (field_count == NUM) \ 217 | constexpr auto to_tuple(T&& t) \ 218 | { \ 219 | auto [__VA_ARGS__] = std::forward(t); \ 220 | return std::tuple( \ 221 | FIELD_RFL_MAP_LIST(FIELD_RFL_FORWARD, __VA_ARGS__)); \ 222 | } 223 | 224 | TO_TUPLE_TEMPLATE(1, p0) 225 | TO_TUPLE_TEMPLATE(2, p0, p1) 226 | TO_TUPLE_TEMPLATE(3, p0, p1, p2) 227 | TO_TUPLE_TEMPLATE(4, p0, p1, p2, p3) 228 | TO_TUPLE_TEMPLATE(5, p0, p1, p2, p3, p4) 229 | TO_TUPLE_TEMPLATE(6, p0, p1, p2, p3, p4, p5) 230 | TO_TUPLE_TEMPLATE(7, p0, p1, p2, p3, p4, p5, p6) 231 | TO_TUPLE_TEMPLATE(8, p0, p1, p2, p3, p4, p5, p6, p7) 232 | TO_TUPLE_TEMPLATE(9, p0, p1, p2, p3, p4, p5, p6, p7, p8) 233 | TO_TUPLE_TEMPLATE(10, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) 234 | TO_TUPLE_TEMPLATE(11, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) 235 | TO_TUPLE_TEMPLATE(12, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) 236 | TO_TUPLE_TEMPLATE(13, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) 237 | TO_TUPLE_TEMPLATE(14, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) 238 | TO_TUPLE_TEMPLATE(15, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) 239 | TO_TUPLE_TEMPLATE(16, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) 240 | TO_TUPLE_TEMPLATE(17, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) 241 | TO_TUPLE_TEMPLATE(18, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) 242 | TO_TUPLE_TEMPLATE(19, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) 243 | TO_TUPLE_TEMPLATE(20, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) 244 | TO_TUPLE_TEMPLATE(21, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 245 | p20) 246 | TO_TUPLE_TEMPLATE(22, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 247 | p20, p21) 248 | TO_TUPLE_TEMPLATE(23, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 249 | p20, p21, p22) 250 | TO_TUPLE_TEMPLATE(24, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 251 | p20, p21, p22, p23) 252 | TO_TUPLE_TEMPLATE(25, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 253 | p20, p21, p22, p23, p24) 254 | TO_TUPLE_TEMPLATE(26, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 255 | p20, p21, p22, p23, p24, p25) 256 | TO_TUPLE_TEMPLATE(27, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 257 | p20, p21, p22, p23, p24, p25, p26) 258 | TO_TUPLE_TEMPLATE(28, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 259 | p20, p21, p22, p23, p24, p25, p26, p27) 260 | TO_TUPLE_TEMPLATE(29, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 261 | p20, p21, p22, p23, p24, p25, p26, p27, p28) 262 | TO_TUPLE_TEMPLATE(30, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 263 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29) 264 | TO_TUPLE_TEMPLATE(31, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 265 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30) 266 | TO_TUPLE_TEMPLATE(32, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 267 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31) 268 | TO_TUPLE_TEMPLATE(33, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 269 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32) 270 | TO_TUPLE_TEMPLATE(34, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 271 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33) 272 | TO_TUPLE_TEMPLATE(35, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 273 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34) 274 | TO_TUPLE_TEMPLATE(36, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 275 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35) 276 | TO_TUPLE_TEMPLATE(37, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 277 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36) 278 | TO_TUPLE_TEMPLATE(38, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 279 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37) 280 | TO_TUPLE_TEMPLATE(39, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 281 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38) 282 | TO_TUPLE_TEMPLATE(40, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 283 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 284 | p39) 285 | TO_TUPLE_TEMPLATE(41, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 286 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 287 | p39, p40) 288 | TO_TUPLE_TEMPLATE(42, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 289 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 290 | p39, p40, p41) 291 | TO_TUPLE_TEMPLATE(43, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 292 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 293 | p39, p40, p41, p42) 294 | TO_TUPLE_TEMPLATE(44, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 295 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 296 | p39, p40, p41, p42, p43) 297 | TO_TUPLE_TEMPLATE(45, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 298 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 299 | p39, p40, p41, p42, p43, p44) 300 | TO_TUPLE_TEMPLATE(46, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 301 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 302 | p39, p40, p41, p42, p43, p44, p45) 303 | TO_TUPLE_TEMPLATE(47, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 304 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 305 | p39, p40, p41, p42, p43, p44, p45, p46) 306 | TO_TUPLE_TEMPLATE(48, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 307 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 308 | p39, p40, p41, p42, p43, p44, p45, p46, p47) 309 | TO_TUPLE_TEMPLATE(49, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 310 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 311 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48) 312 | TO_TUPLE_TEMPLATE(50, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 313 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 314 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49) 315 | TO_TUPLE_TEMPLATE(51, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 316 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 317 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50) 318 | TO_TUPLE_TEMPLATE(52, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 319 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 320 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51) 321 | TO_TUPLE_TEMPLATE(53, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 322 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 323 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52) 324 | TO_TUPLE_TEMPLATE(54, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 325 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 326 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53) 327 | TO_TUPLE_TEMPLATE(55, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 328 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 329 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54) 330 | TO_TUPLE_TEMPLATE(56, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 331 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 332 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55) 333 | TO_TUPLE_TEMPLATE(57, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 334 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 335 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56) 336 | TO_TUPLE_TEMPLATE(58, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 337 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 338 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57) 339 | TO_TUPLE_TEMPLATE(59, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 340 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 341 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 342 | p58) 343 | TO_TUPLE_TEMPLATE(60, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 344 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 345 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 346 | p58, p59) 347 | TO_TUPLE_TEMPLATE(61, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 348 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 349 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 350 | p58, p59, p60) 351 | TO_TUPLE_TEMPLATE(62, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 352 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 353 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 354 | p58, p59, p60, p61) 355 | TO_TUPLE_TEMPLATE(63, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 356 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 357 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 358 | p58, p59, p60, p61, p62) 359 | TO_TUPLE_TEMPLATE(64, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 360 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 361 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 362 | p58, p59, p60, p61, p62, p63) 363 | TO_TUPLE_TEMPLATE(65, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 364 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 365 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 366 | p58, p59, p60, p61, p62, p63, p64) 367 | TO_TUPLE_TEMPLATE(66, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 368 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 369 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 370 | p58, p59, p60, p61, p62, p63, p64, p65) 371 | TO_TUPLE_TEMPLATE(67, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 372 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 373 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 374 | p58, p59, p60, p61, p62, p63, p64, p65, p66) 375 | TO_TUPLE_TEMPLATE(68, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 376 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 377 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 378 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67) 379 | TO_TUPLE_TEMPLATE(69, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 380 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 381 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 382 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68) 383 | TO_TUPLE_TEMPLATE(70, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 384 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 385 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 386 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69) 387 | TO_TUPLE_TEMPLATE(71, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 388 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 389 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 390 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70) 391 | TO_TUPLE_TEMPLATE(72, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 392 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 393 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 394 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71) 395 | TO_TUPLE_TEMPLATE(73, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 396 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 397 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 398 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72) 399 | TO_TUPLE_TEMPLATE(74, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 400 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 401 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 402 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73) 403 | TO_TUPLE_TEMPLATE(75, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 404 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 405 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 406 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74) 407 | TO_TUPLE_TEMPLATE(76, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 408 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 409 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 410 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75) 411 | TO_TUPLE_TEMPLATE(77, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 412 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 413 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 414 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76) 415 | TO_TUPLE_TEMPLATE(78, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 416 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 417 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 418 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 419 | p77) 420 | TO_TUPLE_TEMPLATE(79, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 421 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 422 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 423 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 424 | p77, p78) 425 | TO_TUPLE_TEMPLATE(80, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 426 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 427 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 428 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 429 | p77, p78, p79) 430 | TO_TUPLE_TEMPLATE(81, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 431 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 432 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 433 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 434 | p77, p78, p79, p80) 435 | TO_TUPLE_TEMPLATE(82, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 436 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 437 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 438 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 439 | p77, p78, p79, p80, p81) 440 | TO_TUPLE_TEMPLATE(83, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 441 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 442 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 443 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 444 | p77, p78, p79, p80, p81, p82) 445 | TO_TUPLE_TEMPLATE(84, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 446 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 447 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 448 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 449 | p77, p78, p79, p80, p81, p82, p83) 450 | TO_TUPLE_TEMPLATE(85, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 451 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 452 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 453 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 454 | p77, p78, p79, p80, p81, p82, p83, p84) 455 | TO_TUPLE_TEMPLATE(86, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 456 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 457 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 458 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 459 | p77, p78, p79, p80, p81, p82, p83, p84, p85) 460 | TO_TUPLE_TEMPLATE(87, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 461 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 462 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 463 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 464 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86) 465 | TO_TUPLE_TEMPLATE(88, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 466 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 467 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 468 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 469 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87) 470 | TO_TUPLE_TEMPLATE(89, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 471 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 472 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 473 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 474 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88) 475 | TO_TUPLE_TEMPLATE(90, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 476 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 477 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 478 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 479 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89) 480 | TO_TUPLE_TEMPLATE(91, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 481 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 482 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 483 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 484 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90) 485 | TO_TUPLE_TEMPLATE(92, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 486 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 487 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 488 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 489 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91) 490 | TO_TUPLE_TEMPLATE(93, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 491 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 492 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 493 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 494 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92) 495 | TO_TUPLE_TEMPLATE(94, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 496 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 497 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 498 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 499 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93) 500 | TO_TUPLE_TEMPLATE(95, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 501 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 502 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 503 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 504 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94) 505 | TO_TUPLE_TEMPLATE(96, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 506 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 507 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 508 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 509 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95) 510 | TO_TUPLE_TEMPLATE(97, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 511 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 512 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 513 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 514 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 515 | p96) 516 | TO_TUPLE_TEMPLATE(98, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 517 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 518 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 519 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 520 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 521 | p96, p97) 522 | TO_TUPLE_TEMPLATE(99, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 523 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 524 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 525 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 526 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 527 | p96, p97, p98) 528 | TO_TUPLE_TEMPLATE(100, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, 529 | p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, 530 | p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, 531 | p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, 532 | p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, 533 | p96, p97, p98, p99) 534 | #undef FIELD_RFL_EVAL0 535 | #undef FIELD_RFL_EVAL1 536 | #undef FIELD_RFL_EVAL2 537 | #undef FIELD_RFL_EVAL3 538 | #undef FIELD_RFL_EVAL4 539 | #undef FIELD_RFL_EVAL 540 | #undef FIELD_RFL_MAP_END 541 | #undef FIELD_RFL_MAP_OUT 542 | #undef FIELD_RFL_MAP_COMMA 543 | #undef FIELD_RFL_MAP_GET_END2 544 | #undef FIELD_RFL_MAP_GET_END1 545 | #undef FIELD_RFL_MAP_GET_END 546 | #undef FIELD_RFL_MAP_NEXT0 547 | #undef FIELD_RFL_MAP_NEXT1 548 | #undef FIELD_RFL_MAP_NEXT 549 | #undef FIELD_RFL_MAP0 550 | #undef FIELD_RFL_MAP1 551 | #undef FIELD_RFL_MAP_LIST_NEXT1 552 | #undef FIELD_RFL_MAP_LIST_NEXT 553 | #undef FIELD_RFL_MAP_LIST0 554 | #undef FIELD_RFL_MAP_LIST1 555 | #undef FIELD_RFL_MAP 556 | #undef FIELD_RFL_MAP_LIST 557 | #undef FIELD_RFL_DECLTYPE 558 | #undef FIELD_RFL_MOVE 559 | #undef FIELD_RFL_TO_TUPLE_TEMPLATE 560 | #pragma endregion TO_TUPLE_TEMPLATE_MACRO 561 | 562 | #if defined(__clang__) 563 | #pragma clang diagnostic push 564 | #pragma clang diagnostic ignored "-Wundefined-internal" 565 | #pragma clang diagnostic ignored "-Wundefined-var-template" 566 | #elif defined(__GNUC__) 567 | #elif defined(_MSC_VER) 568 | #else 569 | #endif 570 | 571 | template 572 | struct wrapper 573 | { 574 | explicit constexpr wrapper(const T& v) : value(v) {} 575 | T value; 576 | static wrapper fake; // NOLINT 577 | }; 578 | 579 | template // NOLINT 580 | consteval auto get_ptr() noexcept 581 | { 582 | #if defined(__clang__) 583 | return wrapper(std::get(to_ptr_tuple(wrapper::fake.value))); 584 | #else 585 | return std::get(to_ptr_tuple(wrapper::fake.value)); 586 | #endif 587 | } 588 | 589 | #if defined(__clang__) 590 | #pragma clang diagnostic pop 591 | #elif __GNUC__ 592 | #elif defined(_MSC_VER) 593 | #else 594 | #endif 595 | 596 | template 597 | using nontype_template_parameter_helper = void; 598 | 599 | template // clang-format off 600 | concept field_namable = field_referenceable && (field_count > 0) && requires { 601 | typename nontype_template_parameter_helper()>; 602 | }; // clang-format on 603 | 604 | template 605 | consteval std::string_view get_function_name() 606 | { 607 | #if defined(__clang__) && defined(_WIN32) 608 | // clang-cl returns function_name() as __FUNCTION__ instead of __PRETTY_FUNCTION__ 609 | return std::string_view{__PRETTY_FUNCTION__}; 610 | #else 611 | return std::string_view{std::source_location::current().function_name()}; 612 | #endif 613 | } 614 | 615 | template 616 | consteval std::string_view get_function_name() 617 | { 618 | #if defined(__clang__) && defined(_WIN32) 619 | // clang-cl returns function_name() as __FUNCTION__ instead of __PRETTY_FUNCTION__ 620 | return std::string_view{__PRETTY_FUNCTION__}; 621 | #else 622 | return std::string_view{std::source_location::current().function_name()}; 623 | #endif 624 | } 625 | 626 | template 627 | consteval std::string_view get_field_name() 628 | { 629 | struct field_name_detector 630 | { 631 | void* dummy; 632 | }; 633 | 634 | constexpr auto detector_name = get_function_name()>(); 635 | constexpr auto dummy_begin = detector_name.rfind(std::string_view("dummy")); 636 | constexpr auto suffix = detector_name.substr(dummy_begin + std::string_view("dummy").size()); 637 | constexpr auto begin_sentinel = detector_name[dummy_begin - 1]; 638 | 639 | const auto field_name_raw = get_function_name(); 640 | const auto last = field_name_raw.rfind(suffix); 641 | const auto begin = field_name_raw.rfind(begin_sentinel, last - 1) + 1; 642 | 643 | assert(begin < field_name_raw.size()); 644 | assert(last <= field_name_raw.size()); 645 | assert(begin < last); 646 | 647 | return field_name_raw.substr(begin, last - begin); 648 | } 649 | 650 | template 651 | using remove_rvalue_reference_t = 652 | std::conditional_t, std::remove_reference_t, T>; 653 | 654 | template 655 | constexpr std::string_view field_name = get_field_name()>(); 656 | 657 | template 658 | using field_type = remove_rvalue_reference_t(to_tuple(std::declval())))>; 659 | 660 | struct type_name_detector 661 | { 662 | }; 663 | 664 | template 665 | consteval std::string_view get_type_name() 666 | { 667 | #if defined(__GNUC__) || defined(__clang__) 668 | constexpr auto detector_name = get_function_name(); 669 | constexpr auto dummy = std::string_view("T = "); 670 | constexpr auto dummy_begin = detector_name.find(dummy) + dummy.size(); 671 | constexpr auto dummy2 = std::string_view("type_name_detector"); 672 | constexpr auto dummy_suffix_length = detector_name.size() - detector_name.find(dummy2) - dummy2.size(); 673 | 674 | constexpr auto type_name_raw = get_function_name(); 675 | return type_name_raw.substr(dummy_begin, type_name_raw.size() - dummy_begin - dummy_suffix_length); 676 | #else 677 | constexpr auto detector_name = get_function_name(); 678 | constexpr auto dummy = std::string_view("struct field_reflection::detail::type_name_detector"); 679 | constexpr auto dummy_begin = detector_name.find(dummy); 680 | constexpr auto dummy_suffix_length = detector_name.size() - dummy_begin - dummy.size(); 681 | 682 | auto type_name_raw = get_function_name(); 683 | auto type_name = 684 | type_name_raw.substr(dummy_begin, type_name_raw.size() - dummy_begin - dummy_suffix_length); 685 | if (auto s = std::string_view("struct "); type_name.starts_with(s)) 686 | { 687 | type_name.remove_prefix(s.size()); 688 | } 689 | if (auto s = std::string_view("class "); type_name.starts_with(s)) 690 | { 691 | type_name.remove_prefix(s.size()); 692 | } 693 | return type_name; 694 | #endif 695 | } 696 | 697 | template 698 | constexpr std::string_view type_name = get_type_name(); 699 | 700 | template > 701 | constexpr decltype(auto) get_field(T& t) noexcept 702 | { 703 | return *std::get(to_ptr_tuple(t)); 704 | } 705 | 706 | template > 707 | requires std::is_rvalue_reference_v 708 | constexpr auto get_field(T&& t) noexcept 709 | { 710 | return std::get(to_tuple(std::forward(t))); 711 | } 712 | 713 | template > 714 | void for_each_field_impl(T&& t, Func&& func, std::index_sequence) 715 | { 716 | if constexpr (requires { (func(get_field(t)), ...); }) 717 | { 718 | (func(get_field(t)), ...); 719 | } 720 | else if constexpr (requires { (func(field_name, get_field(t)), ...); }) 721 | { 722 | (func(field_name, get_field(t)), ...); 723 | } 724 | else 725 | { 726 | static_assert([] { return false; }(), "invalid function object for call to for_each_field"); 727 | } 728 | } 729 | 730 | template > 732 | void for_each_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) 733 | { 734 | if constexpr (requires { (func(get_field(t1), get_field(t2)), ...); }) 735 | { 736 | (func(get_field(t1), get_field(t2)), ...); 737 | } 738 | else if constexpr (requires { (func(field_name, get_field(t1), get_field(t2)), ...); }) 739 | { 740 | (func(field_name, get_field(t1), get_field(t2)), ...); 741 | } 742 | else 743 | { 744 | static_assert([] { return false; }(), "invalid function object for call to for_each_field"); 745 | } 746 | } 747 | 748 | template > 749 | bool all_of_field_impl(T&& t, Func&& func, std::index_sequence) 750 | { 751 | if constexpr (requires { (func(get_field(t)) && ...); }) 752 | { 753 | return (func(get_field(t)) && ...); 754 | } 755 | else if constexpr (requires { (func(field_name, get_field(t)) && ...); }) 756 | { 757 | return (func(field_name, get_field(t)) && ...); 758 | } 759 | else 760 | { 761 | static_assert([] { return false; }(), "invalid function object for call to all_of_field"); 762 | } 763 | } 764 | 765 | template > 767 | bool all_of_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) 768 | { 769 | if constexpr (requires { (func(get_field(t1), get_field(t2)) && ...); }) 770 | { 771 | return (func(get_field(t1), get_field(t2)) && ...); 772 | } 773 | else if constexpr (requires { (func(field_name, get_field(t1), get_field(t2)) && ...); }) 774 | { 775 | return (func(field_name, get_field(t1), get_field(t2)) && ...); 776 | } 777 | else 778 | { 779 | static_assert([] { return false; }(), "invalid function object for call to all_of_field"); 780 | } 781 | } 782 | 783 | template > 784 | bool any_of_field_impl(T&& t, Func&& func, std::index_sequence) 785 | { 786 | if constexpr (requires { (func(get_field(t)) || ...); }) 787 | { 788 | return (func(get_field(t)) || ...); 789 | } 790 | else if constexpr (requires { (func(field_name, get_field(t)) || ...); }) 791 | { 792 | return (func(field_name, get_field(t)) || ...); 793 | } 794 | else 795 | { 796 | static_assert([] { return false; }(), "invalid function object for call to any_of_field"); 797 | } 798 | } 799 | 800 | template > 802 | bool any_of_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) 803 | { 804 | if constexpr (requires { (func(get_field(t1), get_field(t2)) || ...); }) 805 | { 806 | return (func(get_field(t1), get_field(t2)) || ...); 807 | } 808 | else if constexpr (requires { (func(field_name, get_field(t1), get_field(t2)) || ...); }) 809 | { 810 | return (func(field_name, get_field(t1), get_field(t2)) || ...); 811 | } 812 | else 813 | { 814 | static_assert([] { return false; }(), "invalid function object for call to any_of_field"); 815 | } 816 | } 817 | } // namespace detail 818 | 819 | using detail::field_count; 820 | using detail::field_countable; 821 | using detail::field_namable; 822 | using detail::field_name; 823 | using detail::field_referenceable; 824 | using detail::field_type; 825 | using detail::get_field; 826 | using detail::to_tuple; 827 | using detail::type_name; 828 | 829 | template , 830 | field_referenceable U2 = std::remove_cvref_t> 831 | requires std::is_same_v 832 | void for_each_field(T1&& t1, T2&& t2, Func&& func) 833 | { 834 | detail::for_each_field_impl(std::forward(t1), std::forward(t2), std::forward(func), 835 | std::make_index_sequence>()); 836 | } 837 | 838 | template > 839 | void for_each_field(T&& t, Func&& func) 840 | { 841 | detail::for_each_field_impl(std::forward(t), std::forward(func), 842 | std::make_index_sequence>()); 843 | } 844 | 845 | template , 846 | field_referenceable U2 = std::remove_cvref_t> 847 | requires std::is_same_v 848 | bool all_of_field(T1&& t1, T2&& t2, Func&& func) 849 | { 850 | return detail::all_of_field_impl(std::forward(t1), std::forward(t2), std::forward(func), 851 | std::make_index_sequence>()); 852 | } 853 | 854 | template > 855 | bool all_of_field(T&& t, Func&& func) 856 | { 857 | return detail::all_of_field_impl(std::forward(t), std::forward(func), 858 | std::make_index_sequence>()); 859 | } 860 | 861 | template , 862 | field_referenceable U2 = std::remove_cvref_t> 863 | requires std::is_same_v 864 | bool any_of_field(T1&& t1, T2&& t2, Func&& func) 865 | { 866 | return detail::any_of_field_impl(std::forward(t1), std::forward(t2), std::forward(func), 867 | std::make_index_sequence>()); 868 | } 869 | 870 | template > 871 | bool any_of_field(T&& t, Func&& func) 872 | { 873 | return detail::any_of_field_impl(std::forward(t), std::forward(func), 874 | std::make_index_sequence>()); 875 | } 876 | } // namespace field_reflection 877 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | # 4 | # COMPILER/LINKER FLAGS 5 | # 6 | set(CMAKE_CXX_STANDARD 20) 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 9 | set(ENV{CMAKE_EXPORT_COMPILE_COMMANDS} ON) 10 | 11 | if(UNIX) 12 | # Warnings 13 | set(CMAKE_CXX_FLAGS 14 | "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wcast-align -Wcast-qual -Wdelete-non-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wpointer-arith -Winit-self -Wredundant-decls -Wsign-promo -Wswitch-default -Wswitch-enum -Wvariadic-macros -Wwrite-strings -Wno-unknown-pragmas" 15 | ) 16 | 17 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") 19 | elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow=local -Wno-pragmas") 21 | endif() 22 | else() # WIN32 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") 24 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") 25 | endif() 26 | 27 | # O3 optimization 28 | if(NOT MSVC) 29 | string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELWITHDEBINFO 30 | ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) 31 | string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) 32 | endif() 33 | 34 | # GTest 35 | find_package(GTest REQUIRED) 36 | include_directories(${GTEST_INCLUDE_DIRS}) 37 | 38 | # executables 39 | add_executable("${PROJECT_NAME}_test" test.cpp) 40 | target_link_libraries("${PROJECT_NAME}_test" 41 | PRIVATE ${PROJECT_NAME} GTest::gtest GTest::gtest_main) 42 | 43 | # add google test 44 | include(GoogleTest) 45 | gtest_discover_tests("${PROJECT_NAME}_test" DISCOVERY_MODE PRE_TEST) 46 | 47 | # compile commands 48 | if(CMAKE_EXPORT_COMPILE_COMMANDS) 49 | add_custom_target( 50 | gen_compile_commands ALL 51 | COMMENT "Generating compile_commands.json" 52 | DEPENDS ${PROJECT_NAME}_test) 53 | 54 | # Remove old file 55 | add_custom_command( 56 | TARGET gen_compile_commands 57 | POST_BUILD 58 | COMMAND ${CMAKE_COMMAND} -E remove 59 | ${CMAKE_SOURCE_DIR}/compile_commands.json) 60 | 61 | # Generate a compilation database with header files 62 | if(NOT COMPDB) 63 | find_program(COMPDB compdb) 64 | endif() 65 | 66 | if(COMPDB) 67 | add_custom_command( 68 | TARGET gen_compile_commands 69 | POST_BUILD 70 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 71 | COMMAND ${COMPDB} list > ${CMAKE_SOURCE_DIR}/compile_commands.json 72 | COMMENT "Running compdb") 73 | else() 74 | message(AUTHOR_WARNING "'compdb' not found") 75 | 76 | # Copy file instead of compdb 77 | add_custom_command( 78 | TARGET gen_compile_commands 79 | POST_BUILD 80 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 81 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/compile_commands.json 82 | ${CMAKE_SOURCE_DIR}/compile_commands.json 83 | COMMENT "Creating symbolic link") 84 | endif() 85 | endif() 86 | -------------------------------------------------------------------------------- /test/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "field_reflection.hpp" 7 | 8 | // NOLINTBEGIN 9 | using namespace field_reflection; 10 | 11 | struct my_struct1 12 | { 13 | int i = 287; 14 | double d = 3.14; 15 | std::string hello = "Hello World"; 16 | std::array arr = {1, 2, 3}; 17 | std::map map{{"one", 1}, {"two", 2}}; 18 | bool operator==(const my_struct1&) const = default; 19 | }; 20 | 21 | // struct with reference 22 | struct my_struct2 23 | { 24 | int& i; 25 | double& d; 26 | }; 27 | 28 | // struct with const reference 29 | struct my_struct3 30 | { 31 | const int& i = 10; 32 | const double& d = 3.14; 33 | }; 34 | 35 | // struct with pointer member 36 | struct my_struct4 37 | { 38 | const int* i = nullptr; 39 | }; 40 | 41 | // nested struct 42 | struct my_struct5 43 | { 44 | my_struct1 m; 45 | }; 46 | 47 | // derived struct 48 | struct my_struct6 : public my_struct1 49 | { 50 | }; 51 | 52 | // nested derived struct 53 | struct my_struct7 : public my_struct1 54 | { 55 | struct X 56 | { 57 | int a; 58 | std::optional b; 59 | std::string c; 60 | } x; 61 | }; 62 | 63 | // struct with lvalue and rvalue reference 64 | struct my_struct8 65 | { 66 | int&& i; 67 | double& d; 68 | }; 69 | 70 | // local struct 71 | auto func() 72 | { 73 | struct local_struct 74 | { 75 | int a; 76 | }; 77 | return local_struct{}; 78 | } 79 | using my_struct9 = decltype(func()); 80 | 81 | // struct in namespace 82 | namespace named 83 | { 84 | struct my_struct10 85 | { 86 | int x0; 87 | double y0; 88 | }; 89 | } // namespace named 90 | 91 | // struct in unnamed namespace 92 | namespace 93 | { 94 | struct my_struct11 95 | { 96 | int x1; 97 | double y1; 98 | }; 99 | } // namespace 100 | 101 | TEST(field_reflection, concept) 102 | { 103 | static_assert(field_countable); 104 | static_assert(field_countable); 105 | static_assert(field_countable); 106 | static_assert(field_countable); 107 | static_assert(field_countable); 108 | static_assert(field_countable); 109 | static_assert(field_countable); 110 | static_assert(!field_countable); 111 | static_assert(field_countable); 112 | static_assert(field_countable); 113 | static_assert(field_countable); 114 | 115 | static_assert(field_referenceable); 116 | static_assert(field_referenceable); 117 | static_assert(field_referenceable); 118 | static_assert(field_referenceable); 119 | static_assert(field_referenceable); 120 | static_assert(!field_referenceable); 121 | static_assert(!field_referenceable); 122 | static_assert(!field_referenceable); 123 | static_assert(field_referenceable); 124 | static_assert(field_referenceable); 125 | static_assert(field_referenceable); 126 | 127 | static_assert(field_namable); 128 | static_assert(!field_namable); 129 | static_assert(!field_namable); 130 | static_assert(field_namable); 131 | static_assert(field_namable); 132 | static_assert(!field_namable); 133 | static_assert(!field_namable); 134 | static_assert(!field_namable); 135 | static_assert(field_namable); 136 | static_assert(field_namable); 137 | static_assert(field_namable); 138 | } 139 | 140 | TEST(field_reflection, field_count) 141 | { 142 | static_assert(field_count == 5); 143 | static_assert(field_count == 2); 144 | static_assert(field_count == 2); 145 | static_assert(field_count == 1); 146 | static_assert(field_count == 1); 147 | static_assert(field_count == 5); 148 | static_assert(field_count == 6); 149 | static_assert(field_count == 1); 150 | static_assert(field_count == 2); 151 | static_assert(field_count == 2); 152 | } 153 | 154 | TEST(field_reflection, field_type) 155 | { 156 | static_assert(std::is_same_v, decltype(std::declval().i)>); 157 | static_assert(std::is_same_v, decltype(std::declval().d)>); 158 | static_assert(std::is_same_v, decltype(std::declval().hello)>); 159 | static_assert(std::is_same_v, decltype(std::declval().arr)>); 160 | static_assert(std::is_same_v, decltype(std::declval().map)>); 161 | 162 | static_assert(std::is_same_v, decltype(std::declval().i)>); 163 | static_assert(std::is_same_v, decltype(std::declval().d)>); 164 | 165 | static_assert(std::is_same_v, decltype(std::declval().i)>); 166 | static_assert(std::is_same_v, decltype(std::declval().d)>); 167 | 168 | static_assert(std::is_same_v, decltype(std::declval().i)>); 169 | static_assert(std::is_same_v, decltype(std::declval().m)>); 170 | 171 | static_assert(std::is_same_v, decltype(std::declval().a)>); 172 | 173 | static_assert(std::is_same_v, decltype(std::declval().x0)>); 174 | static_assert(std::is_same_v, decltype(std::declval().y0)>); 175 | 176 | static_assert(std::is_same_v, decltype(std::declval().x1)>); 177 | static_assert(std::is_same_v, decltype(std::declval().y1)>); 178 | } 179 | 180 | TEST(field_reflection, field_name) 181 | { 182 | static_assert(field_name == "i"); 183 | static_assert(field_name == "d"); 184 | static_assert(field_name == "hello"); 185 | static_assert(field_name == "arr"); 186 | static_assert(field_name == "map"); 187 | 188 | static_assert(field_name == "i"); 189 | static_assert(field_name == "m"); 190 | 191 | static_assert(field_name == "a"); 192 | 193 | static_assert(field_name == "x0"); 194 | static_assert(field_name == "y0"); 195 | static_assert(field_name == "x1"); 196 | static_assert(field_name == "y1"); 197 | } 198 | 199 | TEST(field_reflection, type_name) 200 | { 201 | static_assert(type_name == "my_struct1"); 202 | static_assert(type_name == "named::my_struct10"); 203 | #if defined(__GNUC__) || defined(__clang__) 204 | static_assert(type_name> == "std::pair"); 205 | #else 206 | static_assert(type_name> == "std::pair"); 207 | #endif 208 | } 209 | 210 | TEST(field_reflection, get_field) 211 | { 212 | { 213 | auto ms1 = my_struct1{}; 214 | EXPECT_EQ(&get_field<0>(ms1), &ms1.i); 215 | EXPECT_EQ(&get_field<1>(ms1), &ms1.d); 216 | EXPECT_EQ(&get_field<2>(ms1), &ms1.hello); 217 | EXPECT_EQ(&get_field<3>(ms1), &ms1.arr); 218 | EXPECT_EQ(&get_field<4>(ms1), &ms1.map); 219 | static_assert(std::is_same_v(ms1)), decltype(ms1.i)&>); 220 | static_assert(std::is_same_v(ms1)), decltype(ms1.d)&>); 221 | static_assert(std::is_same_v(ms1)), decltype(ms1.hello)&>); 222 | static_assert(std::is_same_v(ms1)), decltype(ms1.arr)&>); 223 | static_assert(std::is_same_v(ms1)), decltype(ms1.map)&>); 224 | 225 | auto& ms1r = ms1; 226 | EXPECT_EQ(&get_field<0>(ms1r), &ms1.i); 227 | EXPECT_EQ(&get_field<1>(ms1r), &ms1.d); 228 | EXPECT_EQ(&get_field<2>(ms1r), &ms1.hello); 229 | EXPECT_EQ(&get_field<3>(ms1r), &ms1.arr); 230 | EXPECT_EQ(&get_field<4>(ms1r), &ms1.map); 231 | static_assert(std::is_same_v(ms1r)), decltype((ms1r.i))>); 232 | static_assert(std::is_same_v(ms1r)), decltype((ms1r.d))>); 233 | static_assert(std::is_same_v(ms1r)), decltype((ms1r.hello))>); 234 | static_assert(std::is_same_v(ms1r)), decltype((ms1r.arr))>); 235 | static_assert(std::is_same_v(ms1r)), decltype((ms1r.map))>); 236 | 237 | const auto& ms1cr = ms1; 238 | EXPECT_EQ(&get_field<0>(ms1cr), &ms1.i); 239 | EXPECT_EQ(&get_field<1>(ms1cr), &ms1.d); 240 | EXPECT_EQ(&get_field<2>(ms1cr), &ms1.hello); 241 | EXPECT_EQ(&get_field<3>(ms1cr), &ms1.arr); 242 | EXPECT_EQ(&get_field<4>(ms1cr), &ms1.map); 243 | static_assert(std::is_same_v(ms1cr)), decltype((ms1cr.i))>); 244 | static_assert(std::is_same_v(ms1cr)), decltype((ms1cr.d))>); 245 | static_assert(std::is_same_v(ms1cr)), decltype((ms1cr.hello))>); 246 | static_assert(std::is_same_v(ms1cr)), decltype((ms1cr.arr))>); 247 | static_assert(std::is_same_v(ms1cr)), decltype((ms1cr.map))>); 248 | 249 | EXPECT_EQ(get_field<0>(my_struct1{}), ms1.i); 250 | EXPECT_EQ(get_field<1>(my_struct1{}), ms1.d); 251 | EXPECT_EQ(get_field<2>(my_struct1{}), ms1.hello); 252 | EXPECT_EQ(get_field<3>(my_struct1{}), ms1.arr); 253 | EXPECT_EQ(get_field<4>(my_struct1{}), ms1.map); 254 | static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.i)>); 255 | static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.d)>); 256 | static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.hello)>); 257 | static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.arr)>); 258 | static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.map)>); 259 | } 260 | 261 | { 262 | int i = 1; 263 | double d = 3.14; 264 | auto ms2 = my_struct2{i, d}; 265 | EXPECT_EQ(get_field<0>(ms2), ms2.i); 266 | EXPECT_EQ(get_field<1>(ms2), ms2.d); 267 | static_assert(std::is_same_v(ms2)), decltype(ms2.i)&>); 268 | static_assert(std::is_same_v(ms2)), decltype(ms2.d)&>); 269 | } 270 | 271 | { 272 | auto ms3 = my_struct3{}; 273 | EXPECT_EQ(get_field<0>(ms3), ms3.i); 274 | EXPECT_EQ(get_field<1>(ms3), ms3.d); 275 | static_assert(std::is_same_v(ms3)), decltype(ms3.i)&>); 276 | static_assert(std::is_same_v(ms3)), decltype(ms3.d)&>); 277 | } 278 | 279 | { 280 | auto ms4 = my_struct4{}; 281 | EXPECT_EQ(get_field<0>(ms4), ms4.i); 282 | static_assert(std::is_same_v(ms4)), decltype(ms4.i)&>); 283 | } 284 | 285 | { 286 | auto ms5 = my_struct5{}; 287 | EXPECT_EQ(get_field<0>(ms5), ms5.m); 288 | static_assert(std::is_same_v(ms5)), decltype(ms5.m)&>); 289 | } 290 | 291 | { 292 | auto ms9 = my_struct9{}; 293 | EXPECT_EQ(get_field<0>(ms9), ms9.a); 294 | static_assert(std::is_same_v(ms9)), decltype(ms9.a)&>); 295 | } 296 | 297 | { 298 | auto ms10 = named::my_struct10{}; 299 | EXPECT_EQ(get_field<0>(ms10), ms10.x0); 300 | EXPECT_EQ(get_field<1>(ms10), ms10.y0); 301 | static_assert(std::is_same_v(ms10)), decltype(ms10.x0)&>); 302 | static_assert(std::is_same_v(ms10)), decltype(ms10.y0)&>); 303 | } 304 | 305 | { 306 | auto ms11 = my_struct11{}; 307 | EXPECT_EQ(get_field<0>(ms11), ms11.x1); 308 | EXPECT_EQ(get_field<1>(ms11), ms11.y1); 309 | static_assert(std::is_same_v(ms11)), decltype(ms11.x1)&>); 310 | static_assert(std::is_same_v(ms11)), decltype(ms11.y1)&>); 311 | } 312 | } 313 | 314 | TEST(field_reflection, to_tuple) 315 | { 316 | auto ms1 = my_struct1{}; 317 | auto& ms1r = ms1; 318 | const auto& ms1cr = ms1; 319 | 320 | auto t = to_tuple(ms1); 321 | EXPECT_EQ(std::get<0>(t), ms1.i); 322 | EXPECT_EQ(std::get<1>(t), ms1.d); 323 | EXPECT_EQ(std::get<2>(t), ms1.hello); 324 | EXPECT_EQ(std::get<3>(t), ms1.arr); 325 | EXPECT_EQ(std::get<4>(t), ms1.map); 326 | EXPECT_NE(&std::get<0>(t), &ms1.i); 327 | EXPECT_NE(&std::get<1>(t), &ms1.d); 328 | EXPECT_NE(&std::get<2>(t), &ms1.hello); 329 | EXPECT_NE(&std::get<3>(t), &ms1.arr); 330 | EXPECT_NE(&std::get<4>(t), &ms1.map); 331 | 332 | auto tr = to_tuple(ms1r); 333 | EXPECT_EQ(std::get<0>(tr), ms1.i); 334 | EXPECT_EQ(std::get<1>(tr), ms1.d); 335 | EXPECT_EQ(std::get<2>(tr), ms1.hello); 336 | EXPECT_EQ(std::get<3>(tr), ms1.arr); 337 | EXPECT_EQ(std::get<4>(tr), ms1.map); 338 | EXPECT_NE(&std::get<0>(tr), &ms1.i); 339 | EXPECT_NE(&std::get<1>(tr), &ms1.d); 340 | EXPECT_NE(&std::get<2>(tr), &ms1.hello); 341 | EXPECT_NE(&std::get<3>(tr), &ms1.arr); 342 | EXPECT_NE(&std::get<4>(tr), &ms1.map); 343 | 344 | auto tcr = to_tuple(ms1cr); 345 | EXPECT_EQ(std::get<0>(tcr), ms1.i); 346 | EXPECT_EQ(std::get<1>(tcr), ms1.d); 347 | EXPECT_EQ(std::get<2>(tcr), ms1.hello); 348 | EXPECT_EQ(std::get<3>(tcr), ms1.arr); 349 | EXPECT_EQ(std::get<4>(tcr), ms1.map); 350 | EXPECT_NE(&std::get<0>(tcr), &ms1.i); 351 | EXPECT_NE(&std::get<1>(tcr), &ms1.d); 352 | EXPECT_NE(&std::get<2>(tcr), &ms1.hello); 353 | EXPECT_NE(&std::get<3>(tcr), &ms1.arr); 354 | EXPECT_NE(&std::get<4>(tcr), &ms1.map); 355 | 356 | auto trr = to_tuple(std::move(ms1)); 357 | auto ms1_a = my_struct1{}; 358 | EXPECT_EQ(std::get<0>(trr), ms1_a.i); 359 | EXPECT_EQ(std::get<1>(trr), ms1_a.d); 360 | EXPECT_EQ(std::get<2>(trr), ms1_a.hello); 361 | EXPECT_EQ(std::get<3>(trr), ms1_a.arr); 362 | EXPECT_EQ(std::get<4>(trr), ms1_a.map); 363 | } 364 | 365 | TEST(field_reflection, for_each_field) 366 | { 367 | auto ms1_a = my_struct1{}; 368 | auto ms1_b = my_struct1{}; 369 | for_each_field(ms1_a, [](auto&) {}); 370 | for_each_field(ms1_a, [](std::string_view, auto&) {}); 371 | for_each_field(ms1_a, ms1_b, [](auto&, auto&) {}); 372 | for_each_field(ms1_a, ms1_b, [](std::string_view, auto&, auto&) {}); 373 | 374 | auto ms3_a = my_struct3{}; 375 | auto ms3_b = my_struct3{}; 376 | for_each_field(ms3_a, [](auto&) {}); 377 | for_each_field(ms3_a, ms3_b, [](auto&, auto&) {}); 378 | 379 | auto ms4_a = my_struct4{}; 380 | auto ms4_b = my_struct4{}; 381 | for_each_field(ms4_a, [](auto&) {}); 382 | for_each_field(ms4_a, [](std::string_view, auto&) {}); 383 | for_each_field(ms4_a, ms4_b, [](auto&, auto&) {}); 384 | for_each_field(ms4_a, ms4_b, [](std::string_view, auto&, auto&) {}); 385 | 386 | auto ms5_a = my_struct5{}; 387 | auto ms5_b = my_struct5{}; 388 | for_each_field(ms5_a, [](auto&) {}); 389 | for_each_field(ms5_a, [](std::string_view, auto&) {}); 390 | for_each_field(ms5_a, ms5_b, [](auto&, auto&) {}); 391 | for_each_field(ms5_a, ms5_b, [](std::string_view, auto&, auto&) {}); 392 | } 393 | 394 | TEST(field_reflection, all_of_field) 395 | { 396 | auto ms1_a = my_struct1{}; 397 | auto ms1_b = my_struct1{}; 398 | EXPECT_TRUE(all_of_field(ms1_a, [](auto&) { return true; })); 399 | EXPECT_TRUE(all_of_field(ms1_a, [](std::string_view, auto&) { return true; })); 400 | EXPECT_TRUE(all_of_field(ms1_a, ms1_b, [](auto&, auto&) { return true; })); 401 | EXPECT_TRUE(all_of_field(ms1_a, ms1_b, [](std::string_view, auto&, auto&) { return true; })); 402 | 403 | auto ms3_a = my_struct3{}; 404 | auto ms3_b = my_struct3{}; 405 | EXPECT_TRUE(all_of_field(ms3_a, [](auto&) { return true; })); 406 | EXPECT_TRUE(all_of_field(ms3_a, ms3_b, [](auto&, auto&) { return true; })); 407 | 408 | auto ms4_a = my_struct4{}; 409 | auto ms4_b = my_struct4{}; 410 | EXPECT_TRUE(all_of_field(ms4_a, [](auto&) { return true; })); 411 | EXPECT_TRUE(all_of_field(ms4_a, [](std::string_view, auto&) { return true; })); 412 | EXPECT_TRUE(all_of_field(ms4_a, ms4_b, [](auto&, auto&) { return true; })); 413 | EXPECT_TRUE(all_of_field(ms4_a, ms4_b, [](std::string_view, auto&, auto&) { return true; })); 414 | 415 | auto ms5_a = my_struct5{}; 416 | auto ms5_b = my_struct5{}; 417 | EXPECT_TRUE(all_of_field(ms5_a, [](auto&) { return true; })); 418 | EXPECT_TRUE(all_of_field(ms5_a, [](std::string_view, auto&) { return true; })); 419 | EXPECT_TRUE(all_of_field(ms5_a, ms5_b, [](auto&, auto&) { return true; })); 420 | EXPECT_TRUE(all_of_field(ms5_a, ms5_b, [](std::string_view, auto&, auto&) { return true; })); 421 | } 422 | 423 | TEST(field_reflection, any_of_field) 424 | { 425 | auto ms1_a = my_struct1{}; 426 | auto ms1_b = my_struct1{}; 427 | EXPECT_FALSE(any_of_field(ms1_a, [](auto&) { return false; })); 428 | EXPECT_FALSE(any_of_field(ms1_a, [](std::string_view, auto&) { return false; })); 429 | EXPECT_FALSE(any_of_field(ms1_a, ms1_b, [](auto&, auto&) { return false; })); 430 | EXPECT_FALSE(any_of_field(ms1_a, ms1_b, [](std::string_view, auto&, auto&) { return false; })); 431 | 432 | auto ms3_a = my_struct3{}; 433 | auto ms3_b = my_struct3{}; 434 | EXPECT_FALSE(any_of_field(ms3_a, [](auto&) { return false; })); 435 | EXPECT_FALSE(any_of_field(ms3_a, ms3_b, [](auto&, auto&) { return false; })); 436 | 437 | auto ms4_a = my_struct4{}; 438 | auto ms4_b = my_struct4{}; 439 | EXPECT_FALSE(any_of_field(ms4_a, [](auto&) { return false; })); 440 | EXPECT_FALSE(any_of_field(ms4_a, [](std::string_view, auto&) { return false; })); 441 | EXPECT_FALSE(any_of_field(ms4_a, ms4_b, [](auto&, auto&) { return false; })); 442 | EXPECT_FALSE(any_of_field(ms4_a, ms4_b, [](std::string_view, auto&, auto&) { return false; })); 443 | 444 | auto ms5_a = my_struct5{}; 445 | auto ms5_b = my_struct5{}; 446 | EXPECT_FALSE(any_of_field(ms5_a, [](auto&) { return false; })); 447 | EXPECT_FALSE(any_of_field(ms5_a, [](std::string_view, auto&) { return false; })); 448 | EXPECT_FALSE(any_of_field(ms5_a, ms5_b, [](auto&, auto&) { return false; })); 449 | EXPECT_FALSE(any_of_field(ms5_a, ms5_b, [](std::string_view, auto&, auto&) { return false; })); 450 | 451 | auto ms9_a = my_struct9{}; 452 | auto ms9_b = my_struct9{}; 453 | EXPECT_FALSE(any_of_field(ms9_a, [](auto&) { return false; })); 454 | EXPECT_FALSE(any_of_field(ms9_a, [](std::string_view, auto&) { return false; })); 455 | EXPECT_FALSE(any_of_field(ms9_a, ms9_b, [](auto&, auto&) { return false; })); 456 | EXPECT_FALSE(any_of_field(ms9_a, ms9_b, [](std::string_view, auto&, auto&) { return false; })); 457 | } 458 | // NOLINTEND 459 | --------------------------------------------------------------------------------