diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a1e925d --- /dev/null +++ b/.clang-format @@ -0,0 +1,242 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 1 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^( IWYU pragma:|/ | TODO)' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Leave +RawStringFormats: + - Language: TextProto + CanonicalDelimiter: '' + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: Custom +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: true + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..f15f170 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,681 @@ +--- +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' +WarningsAsErrors: '' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: file +CheckOptions: + +- key: readability-identifier-naming.PointerParameterPrefix + value: '' +- key: readability-suspicious-call-argument.PrefixSimilarAbove + value: '30' +- key: modernize-replace-disallow-copy-and-assign-macro.MacroName + value: DISALLOW_COPY_AND_ASSIGN +- key: readability-identifier-naming.GlobalConstantIgnoredRegexp + value: '' +- key: modernize-use-auto.MinTypeNameLength + value: '5' +- key: readability-identifier-naming.VirtualMethodPrefix + value: '' +- key: readability-identifier-naming.ConstantMemberSuffix + value: '' +- key: readability-identifier-naming.ConstantParameterPrefix + value: '' +- key: readability-identifier-naming.InlineNamespacePrefix + value: '' +- key: readability-identifier-naming.GlobalConstantPointerIgnoredRegexp + value: '' +- key: readability-inconsistent-declaration-parameter-name.Strict + value: 'false' +- key: readability-identifier-naming.LocalPointerSuffix + value: '' +- key: readability-identifier-naming.StaticVariableIgnoredRegexp + value: '' +- key: readability-identifier-naming.ClassMemberSuffix + value: _ +- key: readability-identifier-naming.ConstexprFunctionSuffix + value: '' +- key: readability-suspicious-call-argument.DiceDissimilarBelow + value: '60' +- key: readability-identifier-naming.GlobalPointerIgnoredRegexp + value: '' +- key: readability-identifier-naming.TemplateTemplateParameterPrefix + value: '' +- key: readability-identifier-naming.StaticVariableCase + value: lower_case +- key: readability-suspicious-call-argument.Equality + value: 'true' +- key: readability-identifier-naming.EnumConstantSuffix + value: '' +- key: readability-identifier-naming.ParameterIgnoredRegexp + value: '' +- key: readability-identifier-naming.GlobalConstantPointerCase + value: CamelCase +- key: readability-identifier-naming.EnumConstantCase + value: CamelCase +- key: readability-identifier-naming.StaticConstantIgnoredRegexp + value: '' +- key: readability-identifier-naming.GlobalPointerSuffix + value: '' +- key: readability-identifier-naming.EnumIgnoredRegexp + value: '' +- key: readability-identifier-naming.MemberIgnoredRegexp + value: '' +- key: readability-identifier-naming.ClassMethodSuffix + value: '' +- key: readability-identifier-naming.LocalVariableCase + value: lower_case +- key: readability-identifier-naming.ValueTemplateParameterSuffix + value: '' +- key: readability-identifier-naming.ConstantMemberPrefix + value: '' +- key: modernize-use-nodiscard.ReplacementString + value: '[[nodiscard]]' +- key: modernize-loop-convert.MakeReverseRangeHeader + value: '' +- key: readability-identifier-naming.GlobalConstantSuffix + value: '' +- key: readability-identifier-naming.EnumCase + value: CamelCase +- key: readability-identifier-naming.MethodIgnoredRegexp + value: '' +- key: readability-identifier-naming.ClassMethodCase + value: lower_case +- key: readability-suspicious-call-argument.SuffixSimilarAbove + value: '30' +- key: readability-identifier-naming.LocalPointerPrefix + value: '' +- key: readability-identifier-naming.ConstexprFunctionPrefix + value: '' +- key: readability-identifier-naming.ClassMemberPrefix + value: '' +- key: readability-identifier-naming.ParameterPackCase + value: lower_case +- key: modernize-loop-convert.UseCxx20ReverseRanges + value: 'true' +- key: readability-identifier-naming.ConstantSuffix + value: '' +- key: google-readability-function-size.LineThreshold + value: '4294967295' +- key: performance-type-promotion-in-math-fn.IncludeStyle + value: llvm +- key: readability-function-cognitive-complexity.DescribeBasicIncrements + value: 'true' +- key: readability-identifier-naming.PrivateMemberSuffix + value: _ +- key: readability-identifier-naming.ClassMemberCase + value: lower_case +- key: readability-identifier-naming.EnumConstantPrefix + value: '' +- key: modernize-loop-convert.MakeReverseRangeFunction + value: '' +- key: readability-inconsistent-declaration-parameter-name.IgnoreMacros + value: 'true' +- key: readability-identifier-naming.StaticConstantSuffix + value: '' +- key: readability-identifier-naming.TypeTemplateParameterIgnoredRegexp + value: '' +- key: readability-identifier-naming.IgnoreFailedSplit + value: 'false' +- key: readability-qualified-auto.AddConstToQualified + value: 'true' +- key: readability-identifier-naming.InlineNamespaceIgnoredRegexp + value: '' +- key: readability-identifier-naming.NamespaceIgnoredRegexp + value: '' +- key: google-global-names-in-headers.HeaderFileExtensions + value: ';h;hh;hpp;hxx' +- key: readability-identifier-naming.ClassMemberIgnoredRegexp + value: '' +- key: readability-uppercase-literal-suffix.IgnoreMacros + value: 'true' +- key: modernize-make-shared.IgnoreMacros + value: 'true' +- key: readability-identifier-naming.ClassMethodPrefix + value: '' +- key: readability-identifier-naming.UnionCase + value: CamelCase +- key: performance-unnecessary-copy-initialization.AllowedTypes + value: '' +- key: readability-identifier-naming.GlobalConstantPrefix + value: '' +- key: readability-identifier-naming.ClassMethodIgnoredRegexp + value: '' +- key: readability-suspicious-call-argument.Levenshtein + value: 'true' +- key: readability-identifier-naming.GlobalFunctionSuffix + value: '' +- key: modernize-use-transparent-functors.SafeMode + value: 'false' +- key: readability-identifier-naming.ValueTemplateParameterPrefix + value: '' +- key: readability-identifier-naming.GlobalPointerPrefix + value: '' +- key: readability-identifier-naming.PrivateMethodSuffix + value: '' +- key: readability-identifier-naming.TemplateParameterSuffix + value: '' +- key: readability-identifier-naming.GlobalFunctionCase + value: lower_case +- key: readability-simplify-boolean-expr.ChainedConditionalAssignment + value: 'false' +- key: readability-identifier-naming.ParameterPackSuffix + value: '' +- key: readability-identifier-naming.ConstantPrefix + value: '' +- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: 'false' +- key: readability-function-size.LineThreshold + value: '4294967295' +- key: performance-inefficient-vector-operation.EnableProto + value: 'false' +- key: modernize-use-override.IgnoreDestructors + value: 'false' +- key: modernize-loop-convert.MaxCopySize + value: '16' +- key: readability-suspicious-call-argument.PrefixDissimilarBelow + value: '25' +- key: modernize-make-shared.MakeSmartPtrFunction + value: 'std::make_shared' +- key: readability-identifier-naming.StaticConstantPrefix + value: '' +- key: portability-simd-intrinsics.Suggest + value: 'false' +- key: readability-identifier-naming.ClassConstantCase + value: lower_case +- key: readability-identifier-naming.PrivateMemberPrefix + value: '' +- key: modernize-make-shared.MakeSmartPtrFunctionHeader + value: '' +- key: readability-identifier-naming.PublicMethodCase + value: lower_case +- key: readability-identifier-naming.ProtectedMethodCase + value: lower_case +- key: readability-identifier-naming.InlineNamespaceCase + value: lower_case +- key: readability-identifier-naming.LocalConstantPointerIgnoredRegexp + value: '' +- key: readability-identifier-naming.FunctionSuffix + value: '' +- key: readability-redundant-string-init.StringNames + value: '::std::basic_string_view;::std::basic_string' +- key: modernize-make-unique.IgnoreDefaultInitialization + value: 'true' +- key: modernize-use-emplace.ContainersWithPushBack + value: '::std::vector;::std::list;::std::deque' +- key: readability-magic-numbers.IgnoreBitFieldsWidths + value: 'true' +- key: readability-identifier-naming.PublicMemberSuffix + value: '' +- key: modernize-make-unique.IncludeStyle + value: llvm +- key: modernize-use-override.OverrideSpelling + value: override +- key: google-readability-function-size.NestingThreshold + value: '4294967295' +- key: readability-identifier-naming.PublicMemberCase + value: lower_case +- key: readability-suspicious-call-argument.LevenshteinDissimilarBelow + value: '50' +- key: readability-identifier-naming.ParameterPackIgnoredRegexp + value: '' +- key: readability-identifier-naming.StructSuffix + value: '' +- key: google-readability-braces-around-statements.ShortStatementLines + value: '1' +- key: readability-identifier-naming.ParameterCase + value: lower_case +- key: readability-identifier-naming.ProtectedMemberCase + value: lower_case +- key: readability-identifier-naming.LocalPointerIgnoredRegexp + value: '' +- key: readability-identifier-naming.AbstractClassSuffix + value: '' +- key: readability-identifier-naming.TypeAliasSuffix + value: '' +- key: modernize-use-emplace.IgnoreImplicitConstructors + value: 'false' +- key: google-build-namespaces.HeaderFileExtensions + value: ';h;hh;hpp;hxx' +- key: readability-identifier-naming.TypedefIgnoredRegexp + value: '' +- key: readability-identifier-naming.GlobalFunctionPrefix + value: '' +- key: readability-identifier-naming.LocalVariableSuffix + value: '' +- key: readability-suspicious-call-argument.Substring + value: 'true' +- key: modernize-use-equals-delete.IgnoreMacros + value: 'true' +- key: readability-identifier-naming.ClassIgnoredRegexp + value: '' +- key: readability-identifier-naming.GlobalFunctionIgnoredRegexp + value: '' +- key: readability-magic-numbers.IgnoreAllFloatingPointValues + value: 'false' +- key: readability-identifier-naming.TemplateParameterPrefix + value: '' +- key: readability-identifier-naming.PrivateMethodPrefix + value: '' +- key: readability-identifier-naming.ParameterPackPrefix + value: '' +- key: readability-suspicious-call-argument.Abbreviations + 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' +- key: readability-uppercase-literal-suffix.NewSuffixes + value: '' +- key: modernize-loop-convert.MinConfidence + value: reasonable +- key: performance-unnecessary-value-param.AllowedTypes + value: '' +- key: readability-uniqueptr-delete-release.PreferResetCall + value: 'false' +- key: readability-identifier-naming.ClassConstantSuffix + value: _ +- key: readability-identifier-naming.FunctionPrefix + value: '' +- key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' +- key: readability-else-after-return.WarnOnUnfixable + value: 'true' +- key: readability-identifier-naming.PublicMethodSuffix + value: '' +- key: readability-identifier-naming.MethodCase + value: lower_case +- key: readability-function-size.BranchThreshold + value: '4294967295' +- key: readability-identifier-naming.FunctionCase + value: lower_case +- key: readability-identifier-naming.ConstexprFunctionIgnoredRegexp + value: '' +- key: readability-implicit-bool-conversion.AllowIntegerConditions + value: 'false' +- key: readability-identifier-naming.PublicMemberPrefix + value: '' +- key: readability-function-size.StatementThreshold + value: '800' +- key: readability-identifier-naming.ConstantParameterCase + value: lower_case +- key: readability-identifier-naming.LocalPointerCase + value: lower_case +- key: readability-identifier-naming.ConstexprFunctionCase + value: lower_case +- key: readability-identifier-naming.PublicMemberIgnoredRegexp + value: '' +- key: readability-identifier-naming.IgnoreMainLikeFunctions + value: 'false' +- key: google-runtime-int.SignedTypePrefix + value: int +- key: google-readability-function-size.StatementThreshold + value: '800' +- key: readability-identifier-naming.ClassConstantIgnoredRegexp + value: '' +- key: readability-identifier-naming.MemberCase + value: lower_case +- key: readability-identifier-naming.StructPrefix + value: '' +- key: readability-identifier-naming.AbstractClassPrefix + value: '' +- key: readability-suspicious-call-argument.DiceSimilarAbove + value: '70' +- key: readability-identifier-naming.TypeAliasPrefix + value: '' +- key: readability-identifier-naming.VirtualMethodIgnoredRegexp + value: '' +- key: readability-suspicious-call-argument.Abbreviation + value: 'true' +- key: readability-identifier-naming.UnionIgnoredRegexp + value: '' +- key: readability-identifier-naming.UnionSuffix + value: '' +- key: readability-identifier-naming.LocalVariablePrefix + value: '' +- key: readability-identifier-naming.NamespaceSuffix + value: '' +- key: modernize-use-equals-default.IgnoreMacros + value: 'true' +- key: modernize-use-emplace.SmartPointers + value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr' +- key: readability-identifier-naming.PublicMethodIgnoredRegexp + value: '' +- key: readability-magic-numbers.IgnorePowersOf2IntegerValues + value: 'false' +- key: readability-suspicious-call-argument.JaroWinklerSimilarAbove + value: '85' +- key: readability-identifier-naming.PublicMethodPrefix + value: '' +- key: readability-identifier-naming.ClassConstantPrefix + value: '' +- key: readability-simplify-subscript-expr.Types + value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array' +- key: performance-unnecessary-copy-initialization.ExcludedContainerTypes + value: '' +- key: modernize-replace-auto-ptr.IncludeStyle + value: llvm +- key: performance-move-const-arg.CheckTriviallyCopyableMove + value: 'false' +- key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold + value: '3' +- key: readability-function-size.VariableThreshold + value: '4294967295' +- key: readability-identifier-naming.VariableIgnoredRegexp + value: '' +- key: readability-identifier-naming.TemplateParameterCase + value: CamelCase +- key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' +- key: readability-identifier-naming.GetConfigPerFile + value: 'true' +- key: readability-identifier-naming.PointerParameterCase + value: lower_case +- key: modernize-use-default-member-init.UseAssignment + value: 'false' +- key: readability-identifier-naming.PrivateMemberIgnoredRegexp + value: '' +- key: readability-function-size.NestingThreshold + value: '4294967295' +- key: google-readability-function-size.BranchThreshold + value: '4294967295' +- key: readability-identifier-naming.MemberSuffix + value: '' +- key: readability-identifier-naming.ValueTemplateParameterIgnoredRegexp + value: '' +- key: readability-identifier-naming.PrivateMethodIgnoredRegexp + value: '' +- key: modernize-use-override.AllowOverrideAndFinal + value: 'false' +- key: readability-function-size.ParameterThreshold + value: '4294967295' +- key: readability-identifier-naming.TypeTemplateParameterSuffix + value: '' +- key: readability-function-cognitive-complexity.IgnoreMacros + value: 'false' +- key: modernize-loop-convert.IncludeStyle + value: llvm +- key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons + value: 'false' +- key: readability-identifier-naming.StructIgnoredRegexp + value: '' +- key: readability-identifier-naming.ParameterSuffix + value: '' +- key: readability-identifier-naming.AggressiveDependentMemberLookup + value: 'false' +- key: readability-redundant-smartptr-get.IgnoreMacros + value: 'true' +- key: google-readability-function-size.ParameterThreshold + value: '4294967295' +- key: readability-identifier-naming.UnionPrefix + value: '' +- key: readability-identifier-naming.ConstantIgnoredRegexp + value: '' +- key: readability-identifier-naming.NamespacePrefix + value: '' +- key: readability-identifier-naming.ConstexprVariableSuffix + value: '' +- key: readability-identifier-naming.ConstantPointerParameterSuffix + value: '' +- key: readability-identifier-naming.TypeTemplateParameterCase + value: CamelCase +- key: readability-identifier-naming.StructCase + value: lower_case +- key: modernize-use-emplace.TupleTypes + value: '::std::pair;::std::tuple' +- key: modernize-use-emplace.TupleMakeFunctions + value: '::std::make_pair;::std::make_tuple' +- key: readability-identifier-naming.LocalConstantPointerSuffix + value: '' +- key: readability-identifier-naming.TypedefCase + value: lower_case +- key: modernize-replace-random-shuffle.IncludeStyle + value: llvm +- key: modernize-use-bool-literals.IgnoreMacros + value: 'true' +- key: readability-identifier-naming.ProtectedMemberIgnoredRegexp + value: '' +- key: readability-identifier-naming.GlobalConstantCase + value: lower_case +- key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' +- key: readability-suspicious-call-argument.JaroWinklerDissimilarBelow + value: '75' +- key: modernize-avoid-bind.PermissiveParameterList + value: 'false' +- key: readability-identifier-naming.PrivateMethodCase + value: lower_case +- key: readability-suspicious-call-argument.Suffix + value: 'true' +- key: readability-identifier-naming.ConstexprMethodSuffix + value: '' +- key: readability-identifier-naming.ConstantMemberCase + value: lower_case +- key: readability-identifier-naming.ProtectedMethodIgnoredRegexp + value: '' +- key: readability-identifier-naming.MethodSuffix + value: '' +- key: modernize-use-noexcept.ReplacementString + value: '' +- key: modernize-use-using.IgnoreMacros + value: 'true' +- key: readability-identifier-naming.ConstexprMethodCase + value: lower_case +- key: readability-identifier-naming.TypeAliasIgnoredRegexp + value: '' +- key: readability-identifier-naming.MemberPrefix + value: '' +- key: readability-suspicious-call-argument.MinimumIdentifierNameLength + value: '3' +- key: readability-identifier-naming.LocalConstantSuffix + value: '' +- key: readability-identifier-naming.ClassSuffix + value: '' +- key: modernize-loop-convert.NamingStyle + value: CamelCase +- key: readability-identifier-naming.TypeTemplateParameterPrefix + value: '' +- key: readability-identifier-naming.PrivateMemberCase + value: lower_case +- key: performance-no-automatic-move.AllowedTypes + value: '' +- key: readability-suspicious-call-argument.SubstringDissimilarBelow + value: '40' +- key: google-runtime-int.UnsignedTypePrefix + value: uint +- key: readability-identifier-naming.EnumConstantIgnoredRegexp + value: '' +- key: performance-for-range-copy.WarnOnAllAutoCopies + value: 'false' +- key: readability-identifier-naming.ParameterPrefix + value: '' +- key: readability-identifier-naming.TemplateTemplateParameterCase + value: CamelCase +- key: modernize-pass-by-value.IncludeStyle + value: llvm +- key: readability-identifier-naming.ProtectedMemberSuffix + value: _ +- key: readability-identifier-naming.ConstexprVariablePrefix + value: '' +- key: readability-identifier-naming.GlobalConstantPointerSuffix + value: '' +- key: readability-simplify-boolean-expr.ChainedConditionalReturn + value: 'false' +- key: readability-identifier-naming.ConstantPointerParameterPrefix + value: '' +- key: modernize-use-override.FinalSpelling + value: final +- key: readability-else-after-return.WarnOnConditionVariables + value: 'true' +- key: modernize-use-nullptr.NullMacros + value: 'NULL' +- key: readability-suspicious-call-argument.SuffixDissimilarBelow + value: '25' +- key: readability-identifier-naming.LocalConstantPointerPrefix + value: '' +- key: readability-suspicious-call-argument.LevenshteinSimilarAbove + value: '66' +- key: readability-identifier-naming.NamespaceCase + value: lower_case +- key: modernize-make-shared.IgnoreDefaultInitialization + value: 'true' +- key: readability-suspicious-call-argument.JaroWinkler + value: 'true' +- key: readability-identifier-naming.GlobalPointerCase + value: lower_case +- key: modernize-make-shared.IncludeStyle + value: llvm +- key: readability-identifier-naming.LocalConstantPointerCase + value: lower_case +- key: readability-suspicious-call-argument.Prefix + value: 'true' +- key: readability-identifier-naming.ConstexprMethodPrefix + value: '' +- key: readability-identifier-naming.ValueTemplateParameterCase + value: CamelCase +- key: readability-identifier-naming.MethodPrefix + value: '' +- key: readability-identifier-naming.ConstexprMethodIgnoredRegexp + value: '' +- key: readability-identifier-naming.AbstractClassIgnoredRegexp + value: '' +- key: readability-identifier-naming.ConstantParameterIgnoredRegexp + value: '' +- key: readability-identifier-naming.ProtectedMethodSuffix + value: '' +- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: 'true' +- key: readability-identifier-naming.LocalConstantPrefix + value: '' +- key: modernize-make-unique.IgnoreMacros + value: 'true' +- key: readability-identifier-naming.ConstantCase + value: lower_case +- key: performance-for-range-copy.AllowedTypes + value: '' +- key: readability-identifier-naming.ClassPrefix + value: '' +- key: readability-identifier-naming.GlobalConstantPointerPrefix + value: '' +- key: readability-identifier-naming.GlobalVariableSuffix + value: '' +- key: readability-identifier-naming.StaticConstantCase + value: lower_case +- key: readability-identifier-naming.ProtectedMemberPrefix + value: '' +- key: readability-identifier-naming.ClassCase + value: lower_case +- key: readability-identifier-naming.GlobalVariableCase + value: lower_case +- key: readability-identifier-naming.PointerParameterIgnoredRegexp + value: '' +- key: readability-magic-numbers.IgnoredFloatingPointValues + value: '1.0;100.0;' +- key: performance-inefficient-string-concatenation.StrictMode + value: 'false' +- key: readability-implicit-bool-conversion.AllowPointerConditions + value: 'false' +- key: readability-identifier-naming.VirtualMethodCase + value: lower_case +- key: readability-identifier-naming.VariableSuffix + value: '' +- key: modernize-make-unique.MakeSmartPtrFunction + value: 'std::make_unique' +- key: google-runtime-int.TypeSuffix + value: '' +- key: portability-restrict-system-includes.Includes + value: '*' +- key: readability-identifier-naming.StaticVariableSuffix + value: '' +- key: readability-identifier-naming.LocalVariableIgnoredRegexp + value: '' +- key: modernize-make-unique.MakeSmartPtrFunctionHeader + value: '' +- key: readability-suspicious-call-argument.SubstringSimilarAbove + value: '50' +- key: readability-identifier-naming.TypedefSuffix + value: '' +- key: readability-identifier-naming.EnumSuffix + value: '' +- key: readability-identifier-naming.PointerParameterSuffix + value: '' +- key: modernize-use-noexcept.UseNoexceptFalse + value: 'true' +- key: readability-function-cognitive-complexity.Threshold + value: '25' +- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: 'true' +- key: readability-identifier-naming.ProtectedMethodPrefix + value: '' +- key: readability-identifier-naming.VirtualMethodSuffix + value: '' +- key: performance-faster-string-find.StringLikeClasses + value: '::std::basic_string;::std::basic_string_view' +- key: readability-identifier-naming.ConstexprVariableIgnoredRegexp + value: '' +- key: google-readability-function-size.VariableThreshold + value: '4294967295' +- key: readability-identifier-naming.InlineNamespaceSuffix + value: '' +- key: readability-identifier-naming.ConstantParameterSuffix + value: '' +- key: readability-identifier-naming.GlobalVariablePrefix + value: '' +- key: modernize-use-default-member-init.IgnoreMacros + value: 'true' +- key: llvm-qualified-auto.AddConstToQualified + value: 'false' +- key: readability-identifier-naming.LocalConstantIgnoredRegexp + value: '' +- key: readability-identifier-naming.GlobalVariableIgnoredRegexp + value: '' +- key: readability-identifier-naming.TemplateTemplateParameterIgnoredRegexp + value: '' +- key: readability-identifier-naming.ConstantPointerParameterIgnoredRegexp + value: '' +- key: readability-identifier-naming.TemplateTemplateParameterSuffix + value: '' +- key: llvm-else-after-return.WarnOnConditionVariables + value: 'false' +- key: readability-identifier-naming.LocalConstantCase + value: lower_case +- key: readability-identifier-naming.VariablePrefix + value: '' +- key: readability-identifier-naming.ConstantMemberIgnoredRegexp + value: '' +- key: modernize-raw-string-literal.DelimiterStem + value: lit +- key: readability-identifier-naming.FunctionIgnoredRegexp + value: '' +- key: readability-suspicious-call-argument.Dice + value: 'true' +- key: readability-identifier-naming.StaticVariablePrefix + value: '' +- key: readability-identifier-naming.TypedefPrefix + value: '' +- key: readability-identifier-naming.VariableCase + value: lower_case +- key: readability-identifier-naming.EnumPrefix + value: '' +- key: modernize-raw-string-literal.ReplaceShorterLiterals + value: 'false' +- key: readability-identifier-naming.AbstractClassCase + value: lower_case +- key: performance-inefficient-vector-operation.VectorLikeClasses + value: '::std::vector' +- key: readability-identifier-naming.ConstexprVariableCase + value: lower_case +- key: readability-magic-numbers.IgnoredIntegerValues + value: '1;2;3;4;' +- key: modernize-use-auto.RemoveStars + value: 'false' +- key: readability-redundant-member-init.IgnoreBaseInCopyConstructors + value: 'false' +- key: performance-unnecessary-value-param.IncludeStyle + value: llvm +- key: portability-simd-intrinsics.Std + value: '' +- key: readability-identifier-naming.ConstantPointerParameterCase + value: lower_case +- key: llvm-else-after-return.WarnOnUnfixable + value: 'false' +- key: readability-identifier-naming.TemplateParameterIgnoredRegexp + value: '' +... diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b8afbf6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf encoding=utf-8 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..b9141bf --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,146 @@ +name: Tests + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + tags: + - "v*" + +concurrency: + group: test-${{ github.ref }} + cancel-in-progress: false + +jobs: + windows-build: + strategy: + fail-fast: false + matrix: + compiler: + [ + { c: "clang-cl", cxx: "clang-cl" }, + { c: "cl", cxx: "cl" }, + ] + name: Windows - ${{ matrix.compiler.cxx }} + runs-on: windows-latest + + env: + triplet: x64-windows + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Configure VS Toolchain + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install dependencies + run: vcpkg install gtest --triplet ${{ env.triplet }} + + - name: Build and test + run: | + rm -rf "${{ github.workspace }}\build" + 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" + # cmake --build "${{ github.workspace }}\build" --config Debug --clean-first + # ctest --test-dir "${{ github.workspace }}\build" -C Debug + cmake --build "${{ github.workspace }}\build" --config Release --clean-first + ctest --test-dir "${{ github.workspace }}\build" -C Release + shell: bash + + ubuntu-build: + strategy: + fail-fast: false + matrix: + compiler: + [ + { c: "gcc-11", cxx: "g++-11" }, + { c: "gcc-12", cxx: "g++-12" }, + { c: "gcc-13", cxx: "g++-13" }, + { + c: "$(brew --prefix llvm@15)/bin/clang", + cxx: "$(brew --prefix llvm@15)/bin/clang++", + }, + { + c: "$(brew --prefix llvm@16)/bin/clang", + cxx: "$(brew --prefix llvm@16)/bin/clang++", + }, + { + c: "$(brew --prefix llvm@17)/bin/clang", + cxx: "$(brew --prefix llvm@17)/bin/clang++", + }, + ] + name: Ubuntu - ${{ matrix.compiler.cxx }} + runs-on: ubuntu-latest + + env: + triplet: x64-linux + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Install compilers + run: | + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + brew install ninja llvm@12 llvm@13 llvm@14 llvm@15 llvm@16 llvm@17 + + - name: Install dependencies + run: CC=${{ matrix.compiler.c }} CXX=${{ matrix.compiler.cxx }} vcpkg install gtest --triplet ${{ env.triplet }} + + - name: Build and test + run: | + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + rm -rf ${{ github.workspace }}/build + 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" + cmake --build ${{ github.workspace }}/build --config Debug --clean-first + ctest --test-dir ${{ github.workspace }}/build -C Debug + cmake --build ${{ github.workspace }}/build --config Release --clean-first + ctest --test-dir ${{ github.workspace }}/build -C Release + + macos-build: + strategy: + fail-fast: false + matrix: + compiler: + [ + { c: "gcc-11", cxx: "g++-11" }, + { c: "gcc-12", cxx: "g++-12" }, + { c: "gcc-13", cxx: "g++-13" }, + { + c: "$(brew --prefix llvm@16)/bin/clang", + cxx: "$(brew --prefix llvm@16)/bin/clang++", + }, + { + c: "$(brew --prefix llvm@17)/bin/clang", + cxx: "$(brew --prefix llvm@17)/bin/clang++", + }, + ] + name: MacOS - ${{ matrix.compiler.cxx }} + runs-on: macos-latest + + env: + triplet: x64-osx + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Install compilers + run: brew install ninja llvm@12 llvm@13 llvm@14 llvm@15 llvm@16 llvm@17 + + - name: Install dependencies + run: CC=${{ matrix.compiler.c }} CXX=${{ matrix.compiler.cxx }} vcpkg install gtest --triplet ${{ env.triplet }} + + - name: Build and test + run: | + rm -rf ${{ github.workspace }}/build + 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" + cmake --build ${{ github.workspace }}/build --config Debug --clean-first + ctest --test-dir ${{ github.workspace }}/build -C Debug + cmake --build ${{ github.workspace }}/build --config Release --clean-first + ctest --test-dir ${{ github.workspace }}/build -C Release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bbbe72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# CMake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +# build directory +build/ + +# etc +**/.vs/ +**/.vscode/ +**/.ccls-cache/ +**/.clangd/ +**/.cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8825476 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.16) +project( + field_reflection + VERSION 0.0.1 + LANGUAGES CXX) + +# check if the project is top-level +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set(FIELD_RFL_IS_TOPLEVEL_PROJECT ON) +else() + set(FIELD_RFL_IS_TOPLEVEL_PROJECT OFF) +endif() + +# options +option(FIELD_RFL_BUILD_TEST "Build ${PROJECT_NAME} tests" + ${FIELD_RFL_IS_TOPLEVEL_PROJECT}) + +# library +include(GNUInstallDirs) +add_library(${PROJECT_NAME} INTERFACE) +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) +target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20) +target_include_directories( + ${PROJECT_NAME} + INTERFACE $ + $) +set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION}) + +# for MSVC +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + target_compile_options(${PROJECT_NAME} INTERFACE /Zc:preprocessor) +endif() + +# install + +# test +if(FIELD_RFL_BUILD_TEST) + enable_testing() + add_subdirectory(test) +endif() diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d26ce25 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Yoshiki Matsuda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..83268f7 --- /dev/null +++ b/README.md @@ -0,0 +1,201 @@ +# field-reflection C++ + +Static reflection for C++ to get field names and types from a struct/class. + +## Features + +* compile-time reflection +* header-only single file +* no user-side macros +* no dependencies + +## Requirements + +C++20 compilers are required to use this library. + +* GCC >= 11 +* Clang >= 15 + * with libc++-16 or later +* MSVC >= 19.37 + * clang-cl >= 16 + +## Usage + +```cpp +#include +#include +#include +#include +#include +#include "field_reflection.hpp" + +using namespace field_reflection; + +struct my_struct +{ + int i = 287; + double d = 3.14; + std::string hello = "Hello World"; + std::array arr = {1, 2, 3}; + std::map map{{"one", 1}, {"two", 2}}; +}; + +// get field names +constexpr auto my_struct_n0 = field_name; // "i"sv +constexpr auto my_struct_n1 = field_name; // "d"sv +constexpr auto my_struct_n2 = field_name; // "hello"sv +constexpr auto my_struct_n3 = field_name; // "arr"sv +constexpr auto my_struct_n4 = field_name; // "map"sv + +// get field types +using my_struct_t0 = field_type; // int +using my_struct_t1 = field_type; // double +using my_struct_t2 = field_type; // std::string +using my_struct_t3 = field_type; // std::array +using my_struct_t4 = field_type; // std::map + +// get field values with index +auto s = my_struct{}; +auto& my_struct_v0 = get_field<0>(s); // s.i +auto& my_struct_v1 = get_field<1>(s); // s.d +auto& my_struct_v2 = get_field<2>(s); // s.hello +auto& my_struct_v3 = get_field<3>(s); // s.arr +auto& my_struct_v4 = get_field<4>(s); // s.map + +// visit each field +for_each_field(s, [](std::string_view field, auto& value) { + // i: 287 + // d: 3.14 + // hello: Hello World + // arr: [1, 2, 3] + // map: {"one": 1, "two": 2} + std::println("{}: {}", field, value); +}); +``` + +## API References + +### Concepts + +```cpp +template +concept field_countable; +template +concept field_namable; +``` + +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 has a default constructor. + +The `field_namable` is a concept that checks if the name of a field can be obtained from the type `T` statically. This also satisfies the `field_countable` concept. + + +### `field_count` + +```cpp +template +constexpr std::size_t field_count; +``` + +Get the number of fields from the `field_countable` type `T`. + +### `field_name` + +```cpp +template +constexpr std::string_view field_name; +``` + +Get the name of the `N`-th field as `std::string_view` from the `field_namable` type `T`. + +### `field_type` + +```cpp +template +using field_type; +``` + +Get the type of the `N`-th field from the `field_countable` type `T`. + +### `get_field` + +```cpp +// reference +template +constexpr auto& get_field(T& t) noexcept; + +// const reference +template +constexpr const auto& get_field(const T& t) noexcept; + +// rvalue reference +template +constexpr auto get_field(T&& t) noexcept; +``` + +Extracts the `N`-th element from the `field_countable` 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. + +### `for_each_field` + +```cpp +// unary operation +template +void for_each_field(T&& t, Func&& func); + +// binary operation +template +void for_each_field(T&& t1, T&& t2, Func&& func); +``` + +Visit each field of the `field_countable` type `T` and apply the unary or binary operation `func` to it. The `func` should be a callable object that takes two kinds of arguments: + +* Arguments of one or two references to the field for the `field_countable` type `T`. +* Arguments of `std::string_view` and one or two references to the field for the `field_namable` type `T`. + +For example, the following code prints the field names and values of the `my_struct` `s`: + +```cpp +constexpr auto func = [](std::string_view field, auto& value) { + std::println("{}: {}", field, value); +}; +for_each_field(s, func); +``` + +The above is equivalent to: + +```cpp +func("i"sv, s.i); +func("d"sv, s.d); +func("hello"sv, s.hello); +func("arr"sv, s.arr); +func("map"sv, s.map); +``` + +The first argument in the definition of the `func` can be omitted if it is not needed. + +The binary operation version of `for_each_field` is useful for comparing each field of two objects of the same type: + +```cpp +constexpr auto func = [](std::string_view field, auto& value1, auto& value2) { + if (value1 != value2) { + std::println("s1 and s2 have a different value: s1.{} = {}, s2.{} = {}", + field, value1, field, value2); + } +}; +for_each_field(s1, s2, func); +``` + +### `to_tuple` + +```cpp +template +constexpr std::tuple<...> to_tuple(T&& t); +``` + +Copy a `field_countable` 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>`. + +## Acknowledgments + +This library is strongly inspired by the following projects and stands as + +* a alternative to [visit_struct](https://github.com/cbeck88/visit_struct) without macros, +* a reflection library that is a partial reimplementation of [reflect-cpp](https://github.com/getml/reflect-cpp) and [glaze](https://github.com/stephenberry/glaze). diff --git a/include/field_reflection.hpp b/include/field_reflection.hpp new file mode 100644 index 0000000..c50f501 --- /dev/null +++ b/include/field_reflection.hpp @@ -0,0 +1,613 @@ +/*===================================================* +| field-reflection version v0.0.1 | +| https://github.com/yosh-matsuda/field-reflection | +| | +| Copyright (c) 2024 Yoshiki Matsuda @yosh-matsuda | +| | +| This software is released under the MIT License. | +| https://opensource.org/license/mit/ | +====================================================*/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace field_reflection +{ + namespace detail + { + struct any + { + explicit any(std::size_t) noexcept; + template + constexpr operator T() const noexcept; // NOLINT + }; + + template + concept constructible_with_arguments = [](std::index_sequence) { + return requires { T{any{Is}...}; }; + }(std::make_index_sequence()); + + template + requires constructible_with_arguments + constexpr std::size_t field_count_impl = []() { + if constexpr (constructible_with_arguments) + { + return field_count_impl; + } + else + { + return N; + } + }(); + + template + concept field_countable = std::is_aggregate_v && constructible_with_arguments; + + template + inline constexpr std::size_t field_count = detail::field_count_impl; + + template > + requires (field_count == 0) + constexpr auto to_ref_tuple(T&&) + { + return std::tie(); + } + +#pragma region TO_TUPLE_TEMPLATE_MACRO +// map macro: https://github.com/swansontec/map-macro +#define FIELD_RFL_EVAL0(...) __VA_ARGS__ +#define FIELD_RFL_EVAL1(...) FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(FIELD_RFL_EVAL0(__VA_ARGS__))) +#define FIELD_RFL_EVAL2(...) FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(FIELD_RFL_EVAL1(__VA_ARGS__))) +#define FIELD_RFL_EVAL3(...) FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(FIELD_RFL_EVAL2(__VA_ARGS__))) +#define FIELD_RFL_EVAL4(...) FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(FIELD_RFL_EVAL3(__VA_ARGS__))) +#define FIELD_RFL_EVAL(...) FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(FIELD_RFL_EVAL4(__VA_ARGS__))) + +#define FIELD_RFL_MAP_END(...) +#define FIELD_RFL_MAP_OUT +#define FIELD_RFL_MAP_COMMA , + +#define FIELD_RFL_MAP_GET_END2() 0, FIELD_RFL_MAP_END +#define FIELD_RFL_MAP_GET_END1(...) FIELD_RFL_MAP_GET_END2 +#define FIELD_RFL_MAP_GET_END(...) FIELD_RFL_MAP_GET_END1 +#define FIELD_RFL_MAP_NEXT0(test, next, ...) next FIELD_RFL_MAP_OUT +#define FIELD_RFL_MAP_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, next, 0) +#define FIELD_RFL_MAP_NEXT(test, next) FIELD_RFL_MAP_NEXT1(FIELD_RFL_MAP_GET_END test, next) + +#define FIELD_RFL_MAP0(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP1)(f, peek, __VA_ARGS__) +#define FIELD_RFL_MAP1(f, x, peek, ...) f(x) FIELD_RFL_MAP_NEXT(peek, FIELD_RFL_MAP0)(f, peek, __VA_ARGS__) + +#define FIELD_RFL_MAP_LIST_NEXT1(test, next) FIELD_RFL_MAP_NEXT0(test, FIELD_RFL_MAP_COMMA next, 0) +#define FIELD_RFL_MAP_LIST_NEXT(test, next) FIELD_RFL_MAP_LIST_NEXT1(FIELD_RFL_MAP_GET_END test, next) + +#define FIELD_RFL_MAP_LIST0(f, x, peek, ...) \ + f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST1)(f, peek, __VA_ARGS__) +#define FIELD_RFL_MAP_LIST1(f, x, peek, ...) \ + f(x) FIELD_RFL_MAP_LIST_NEXT(peek, FIELD_RFL_MAP_LIST0)(f, peek, __VA_ARGS__) +#define FIELD_RFL_MAP(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) +#define FIELD_RFL_MAP_LIST(f, ...) FIELD_RFL_EVAL(FIELD_RFL_MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define FIELD_RFL_DECLTYPE(x) decltype(x) +#define FIELD_RFL_MOVE(x) std::move(x) + +#define TO_TUPLE_TEMPLATE(NUM, ...) \ + template > \ + requires (field_count == NUM) \ + constexpr auto to_ref_tuple(T&& t) \ + { \ + auto& [__VA_ARGS__] = t; \ + return std::tie(__VA_ARGS__); \ + } \ + template > \ + requires (field_count == NUM) \ + constexpr auto to_tuple(T&& t) \ + { \ + auto [__VA_ARGS__] = std::forward(t); \ + return std::tuple( \ + FIELD_RFL_MAP_LIST(FIELD_RFL_MOVE, __VA_ARGS__)); \ + } + + TO_TUPLE_TEMPLATE(1, p0) + TO_TUPLE_TEMPLATE(2, p0, p1) + TO_TUPLE_TEMPLATE(3, p0, p1, p2) + TO_TUPLE_TEMPLATE(4, p0, p1, p2, p3) + TO_TUPLE_TEMPLATE(5, p0, p1, p2, p3, p4) + TO_TUPLE_TEMPLATE(6, p0, p1, p2, p3, p4, p5) + TO_TUPLE_TEMPLATE(7, p0, p1, p2, p3, p4, p5, p6) + TO_TUPLE_TEMPLATE(8, p0, p1, p2, p3, p4, p5, p6, p7) + TO_TUPLE_TEMPLATE(9, p0, p1, p2, p3, p4, p5, p6, p7, p8) + TO_TUPLE_TEMPLATE(10, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) + TO_TUPLE_TEMPLATE(11, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) + TO_TUPLE_TEMPLATE(12, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) + TO_TUPLE_TEMPLATE(13, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) + TO_TUPLE_TEMPLATE(14, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) + TO_TUPLE_TEMPLATE(15, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) + TO_TUPLE_TEMPLATE(16, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) + TO_TUPLE_TEMPLATE(17, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) + TO_TUPLE_TEMPLATE(18, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) + TO_TUPLE_TEMPLATE(19, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) + TO_TUPLE_TEMPLATE(20, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) + TO_TUPLE_TEMPLATE(21, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20) + TO_TUPLE_TEMPLATE(22, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21) + TO_TUPLE_TEMPLATE(23, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22) + TO_TUPLE_TEMPLATE(24, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23) + TO_TUPLE_TEMPLATE(25, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24) + TO_TUPLE_TEMPLATE(26, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25) + TO_TUPLE_TEMPLATE(27, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26) + TO_TUPLE_TEMPLATE(28, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27) + TO_TUPLE_TEMPLATE(29, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28) + TO_TUPLE_TEMPLATE(30, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29) + TO_TUPLE_TEMPLATE(31, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30) + TO_TUPLE_TEMPLATE(32, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31) + TO_TUPLE_TEMPLATE(33, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32) + TO_TUPLE_TEMPLATE(34, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33) + TO_TUPLE_TEMPLATE(35, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34) + TO_TUPLE_TEMPLATE(36, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35) + TO_TUPLE_TEMPLATE(37, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36) + TO_TUPLE_TEMPLATE(38, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37) + TO_TUPLE_TEMPLATE(39, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38) + TO_TUPLE_TEMPLATE(40, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39) + TO_TUPLE_TEMPLATE(41, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40) + TO_TUPLE_TEMPLATE(42, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41) + TO_TUPLE_TEMPLATE(43, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42) + TO_TUPLE_TEMPLATE(44, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43) + TO_TUPLE_TEMPLATE(45, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44) + TO_TUPLE_TEMPLATE(46, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45) + TO_TUPLE_TEMPLATE(47, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46) + TO_TUPLE_TEMPLATE(48, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47) + TO_TUPLE_TEMPLATE(49, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48) + TO_TUPLE_TEMPLATE(50, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49) + TO_TUPLE_TEMPLATE(51, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50) + TO_TUPLE_TEMPLATE(52, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51) + TO_TUPLE_TEMPLATE(53, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52) + TO_TUPLE_TEMPLATE(54, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53) + TO_TUPLE_TEMPLATE(55, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54) + TO_TUPLE_TEMPLATE(56, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55) + TO_TUPLE_TEMPLATE(57, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56) + TO_TUPLE_TEMPLATE(58, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57) + TO_TUPLE_TEMPLATE(59, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58) + TO_TUPLE_TEMPLATE(60, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59) + TO_TUPLE_TEMPLATE(61, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60) + TO_TUPLE_TEMPLATE(62, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61) + TO_TUPLE_TEMPLATE(63, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62) + TO_TUPLE_TEMPLATE(64, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63) + TO_TUPLE_TEMPLATE(65, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64) + TO_TUPLE_TEMPLATE(66, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65) + TO_TUPLE_TEMPLATE(67, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66) + TO_TUPLE_TEMPLATE(68, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67) + TO_TUPLE_TEMPLATE(69, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68) + TO_TUPLE_TEMPLATE(70, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69) + TO_TUPLE_TEMPLATE(71, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70) + TO_TUPLE_TEMPLATE(72, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71) + TO_TUPLE_TEMPLATE(73, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72) + TO_TUPLE_TEMPLATE(74, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73) + TO_TUPLE_TEMPLATE(75, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74) + TO_TUPLE_TEMPLATE(76, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75) + TO_TUPLE_TEMPLATE(77, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76) + TO_TUPLE_TEMPLATE(78, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77) + TO_TUPLE_TEMPLATE(79, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78) + TO_TUPLE_TEMPLATE(80, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79) + TO_TUPLE_TEMPLATE(81, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80) + TO_TUPLE_TEMPLATE(82, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81) + TO_TUPLE_TEMPLATE(83, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82) + TO_TUPLE_TEMPLATE(84, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83) + TO_TUPLE_TEMPLATE(85, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84) + TO_TUPLE_TEMPLATE(86, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85) + TO_TUPLE_TEMPLATE(87, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86) + TO_TUPLE_TEMPLATE(88, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87) + TO_TUPLE_TEMPLATE(89, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88) + TO_TUPLE_TEMPLATE(90, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89) + TO_TUPLE_TEMPLATE(91, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90) + TO_TUPLE_TEMPLATE(92, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91) + TO_TUPLE_TEMPLATE(93, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92) + TO_TUPLE_TEMPLATE(94, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93) + TO_TUPLE_TEMPLATE(95, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94) + TO_TUPLE_TEMPLATE(96, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95) + TO_TUPLE_TEMPLATE(97, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, + p96) + TO_TUPLE_TEMPLATE(98, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, + p96, p97) + TO_TUPLE_TEMPLATE(99, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, + p96, p97, p98) + TO_TUPLE_TEMPLATE(100, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, + p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, + p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, + p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, + p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, + p96, p97, p98, p99) +#undef FIELD_RFL_EVAL0 +#undef FIELD_RFL_EVAL1 +#undef FIELD_RFL_EVAL2 +#undef FIELD_RFL_EVAL3 +#undef FIELD_RFL_EVAL4 +#undef FIELD_RFL_EVAL +#undef FIELD_RFL_MAP_END +#undef FIELD_RFL_MAP_OUT +#undef FIELD_RFL_MAP_COMMA +#undef FIELD_RFL_MAP_GET_END2 +#undef FIELD_RFL_MAP_GET_END1 +#undef FIELD_RFL_MAP_GET_END +#undef FIELD_RFL_MAP_NEXT0 +#undef FIELD_RFL_MAP_NEXT1 +#undef FIELD_RFL_MAP_NEXT +#undef FIELD_RFL_MAP0 +#undef FIELD_RFL_MAP1 +#undef FIELD_RFL_MAP_LIST_NEXT1 +#undef FIELD_RFL_MAP_LIST_NEXT +#undef FIELD_RFL_MAP_LIST0 +#undef FIELD_RFL_MAP_LIST1 +#undef FIELD_RFL_MAP +#undef FIELD_RFL_MAP_LIST +#undef FIELD_RFL_DECLTYPE +#undef FIELD_RFL_MOVE +#undef FIELD_RFL_TO_TUPLE_TEMPLATE +#pragma endregion TO_TUPLE_TEMPLATE_MACRO + + template > + constexpr auto to_ref_tuple(T&&) + { + static_assert([] { return false; }(), "The supported maximum number of fields in struct must be <= 100."); + } + + template + [[nodiscard]] consteval std::string_view mangled_name() + { +#if defined(__clang__) && defined(_WIN32) + // clang-cl returns function_name() as __FUNCTION__ instead of __PRETTY_FUNCTION__ + return __PRETTY_FUNCTION__; +#else + return std::source_location::current().function_name(); +#endif + } + + template + struct pointer_wrapper final + { + T* ptr; + }; + + template + consteval auto cptr(T&& t) noexcept + { + decltype(auto) p = std::get(to_ref_tuple(t)); + return pointer_wrapper>{&p}; + } + + template + using nontype_template_parameter_helper = void; + + template + extern const T external; + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" +#elif __GNUC__ + +#else + +#endif + + template + concept field_namable = + field_countable && requires { typename nontype_template_parameter_helper(external)>; }; + + struct member_name_detector + { + void* dummy; + }; + + template + consteval auto get_field_name() noexcept + { + constexpr auto mangled_dummy = mangled_name(external)>(); + constexpr auto dummy_begin = mangled_dummy.rfind(std::string_view("dummy")); + constexpr auto suffix = mangled_dummy.substr(dummy_begin + std::string_view("dummy").size()); + constexpr auto begin_sentinel = mangled_dummy[dummy_begin - 1]; + + constexpr auto mangled_member_name = mangled_name(external)>(); + constexpr auto last = mangled_member_name.rfind(suffix); + constexpr auto begin = mangled_member_name.rfind(begin_sentinel, last) + 1; + + static_assert(begin < mangled_member_name.size()); + static_assert(last <= mangled_member_name.size()); + static_assert(begin < last); + return mangled_member_name.substr(begin, last - begin); + } + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif __GNUC__ + +#else + +#endif + template + using remove_rvalue_reference_t = + std::conditional_t, std::remove_reference_t, T>; + } // namespace detail + + using detail::field_count; + using detail::field_countable; + using detail::field_namable; + using detail::to_tuple; + + template + constexpr std::string_view field_name = detail::get_field_name(); + + template + using field_type = detail::remove_rvalue_reference_t(detail::to_tuple(std::declval())))>; + + template > + constexpr decltype(auto) get_field(T& t) noexcept + { + return std::get(detail::to_ref_tuple(t)); + } + + template > + requires std::is_rvalue_reference_v + constexpr auto get_field(T&& t) noexcept + { + return std::get(to_tuple(std::forward(t))); + } + + namespace detail + { + template > + requires requires(T1&& t1, T2&& t2, Func&& func, std::index_sequence) { + (func(field_name, get_field(t1), get_field(t2)), ...); + } + void for_each_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) + { + (func(field_name, get_field(t1), get_field(t2)), ...); + } + + template > + requires requires(T&& t, Func&& func, std::index_sequence) { + (func(field_name, get_field(t)), ...); + } + void for_each_field_impl(T&& t, Func&& func, std::index_sequence) + { + (func(field_name, get_field(t)), ...); + } + + template > + requires requires(T1&& t1, T2&& t2, Func&& func, std::index_sequence) { + (func(get_field(t1), get_field(t2)), ...); + } + void for_each_field_impl(T1&& t1, T2&& t2, Func&& func, std::index_sequence) + { + (func(get_field(t1), get_field(t2)), ...); + } + + template > + requires requires(T&& t, Func&& func, std::index_sequence) { (func(get_field(t)), ...); } + void for_each_field_impl(T&& t, Func&& func, std::index_sequence) + { + (func(get_field(t)), ...); + } + } // namespace detail + + template , + field_countable U2 = std::remove_cvref_t> + requires std::is_same_v + void for_each_field(T1&& t1, T2&& t2, Func&& func) + { + detail::for_each_field_impl(std::forward(t1), std::forward(t2), std::forward(func), + std::make_index_sequence>()); + } + + template > + void for_each_field(T&& t, Func&& func) + { + detail::for_each_field_impl(std::forward(t), std::forward(func), + std::make_index_sequence>()); + } +} // namespace field_reflection diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..9850f7d --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.16) + +# +# COMPILER/LINKER FLAGS +# +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(ENV{CMAKE_EXPORT_COMPILE_COMMANDS} ON) + +if(UNIX) + # Warnings + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wcast-align -Wcast-qual -Wdelete-non-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wpointer-arith -Wfloat-equal -Winit-self -Wredundant-decls -Wsign-promo -Wswitch-default -Wswitch-enum -Wvariadic-macros -Wwrite-strings -Wno-unknown-pragmas" + ) + + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") + elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow=local -Wno-pragmas") + endif() +else() # WIN32 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() + +# O3 optimization +if(NOT MSVC) + string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELWITHDEBINFO + ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) + string(REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) +endif() + +# GTest +find_package(GTest REQUIRED) +include_directories(${GTEST_INCLUDE_DIRS}) + +# executables +add_executable("${PROJECT_NAME}_test" test.cpp) +target_link_libraries("${PROJECT_NAME}_test" + PRIVATE ${PROJECT_NAME} GTest::gtest GTest::gtest_main) + +# add google test +include(GoogleTest) +gtest_discover_tests("${PROJECT_NAME}_test" DISCOVERY_MODE PRE_TEST) + +# compile commands +if(CMAKE_EXPORT_COMPILE_COMMANDS) + add_custom_target( + gen_compile_commands ALL + COMMENT "Generating compile_commands.json" + DEPENDS ${PROJECT_NAME}_test) + + # Remove old file + add_custom_command( + TARGET gen_compile_commands + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E remove + ${CMAKE_SOURCE_DIR}/compile_commands.json) + + # Generate a compilation database with header files + if(NOT COMPDB) + find_program(COMPDB compdb) + endif() + + if(COMPDB) + add_custom_command( + TARGET gen_compile_commands + POST_BUILD + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${COMPDB} list > ${CMAKE_SOURCE_DIR}/compile_commands.json + COMMENT "Running compdb") + else() + message(AUTHOR_WARNING "'compdb' not found") + + # Copy file instead of compdb + add_custom_command( + TARGET gen_compile_commands + POST_BUILD + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/compile_commands.json + ${CMAKE_SOURCE_DIR}/compile_commands.json + COMMENT "Creating symbolic link") + endif() +endif() diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 0000000..6f7e21e --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include "field_reflection.hpp" + +// NOLINTBEGIN +using namespace field_reflection; + +struct my_struct1 +{ + int i = 287; + double d = 3.14; + std::string hello = "Hello World"; + std::array arr = {1, 2, 3}; + std::map map{{"one", 1}, {"two", 2}}; +}; + +struct my_struct2 +{ + int& i; +}; + +struct my_struct3 +{ + const int& i = 10; +}; + +struct my_struct4 +{ + const int* i = nullptr; +}; + +TEST(field_reflection, concept) +{ + static_assert(field_countable); + static_assert(!field_countable); + static_assert(field_countable); + static_assert(field_countable); + + static_assert(field_namable); + static_assert(!field_namable); + static_assert(!field_namable); + static_assert(field_namable); +} + +TEST(field_reflection, field_name) +{ + static_assert(field_name == "i"); + static_assert(field_name == "d"); + static_assert(field_name == "hello"); + static_assert(field_name == "arr"); + static_assert(field_name == "map"); + static_assert(field_count == 5); + + static_assert(field_name == "i"); + static_assert(field_count == 1); +} + +TEST(field_reflection, field_type) +{ + static_assert(std::is_same_v, decltype(std::declval().i)>); + static_assert(std::is_same_v, decltype(std::declval().d)>); + static_assert(std::is_same_v, decltype(std::declval().hello)>); + static_assert(std::is_same_v, decltype(std::declval().arr)>); + static_assert(std::is_same_v, decltype(std::declval().map)>); + + static_assert(std::is_same_v, decltype(std::declval().i)>); + static_assert(std::is_same_v, decltype(std::declval().i)>); +} + +TEST(field_reflection, get_field) +{ + auto s = my_struct1{}; + EXPECT_EQ(&get_field<0>(s), &s.i); + EXPECT_EQ(&get_field<1>(s), &s.d); + EXPECT_EQ(&get_field<2>(s), &s.hello); + EXPECT_EQ(&get_field<3>(s), &s.arr); + EXPECT_EQ(&get_field<4>(s), &s.map); + static_assert(std::is_same_v(s)), decltype(s.i)&>); + static_assert(std::is_same_v(s)), decltype(s.d)&>); + static_assert(std::is_same_v(s)), decltype(s.hello)&>); + static_assert(std::is_same_v(s)), decltype(s.arr)&>); + static_assert(std::is_same_v(s)), decltype(s.map)&>); + + auto& sr = s; + EXPECT_EQ(&get_field<0>(sr), &s.i); + EXPECT_EQ(&get_field<1>(sr), &s.d); + EXPECT_EQ(&get_field<2>(sr), &s.hello); + EXPECT_EQ(&get_field<3>(sr), &s.arr); + EXPECT_EQ(&get_field<4>(sr), &s.map); + static_assert(std::is_same_v(sr)), decltype((sr.i))>); + static_assert(std::is_same_v(sr)), decltype((sr.d))>); + static_assert(std::is_same_v(sr)), decltype((sr.hello))>); + static_assert(std::is_same_v(sr)), decltype((sr.arr))>); + static_assert(std::is_same_v(sr)), decltype((sr.map))>); + + const auto& scr = s; + EXPECT_EQ(&get_field<0>(scr), &s.i); + EXPECT_EQ(&get_field<1>(scr), &s.d); + EXPECT_EQ(&get_field<2>(scr), &s.hello); + EXPECT_EQ(&get_field<3>(scr), &s.arr); + EXPECT_EQ(&get_field<4>(scr), &s.map); + static_assert(std::is_same_v(scr)), decltype((scr.i))>); + static_assert(std::is_same_v(scr)), decltype((scr.d))>); + static_assert(std::is_same_v(scr)), decltype((scr.hello))>); + static_assert(std::is_same_v(scr)), decltype((scr.arr))>); + static_assert(std::is_same_v(scr)), decltype((scr.map))>); + + EXPECT_EQ(get_field<0>(my_struct1{}), s.i); + EXPECT_EQ(get_field<1>(my_struct1{}), s.d); + EXPECT_EQ(get_field<2>(my_struct1{}), s.hello); + EXPECT_EQ(get_field<3>(my_struct1{}), s.arr); + EXPECT_EQ(get_field<4>(my_struct1{}), s.map); + static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.i)>); + static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.d)>); + static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.hello)>); + static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.arr)>); + static_assert(std::is_same_v(my_struct1{})), decltype(my_struct1{}.map)>); + + auto crs = my_struct3{}; + EXPECT_EQ(get_field<0>(crs), crs.i); + static_assert(std::is_same_v(crs)), decltype(crs.i)&>); + + auto ps = my_struct4{}; + EXPECT_EQ(get_field<0>(ps), ps.i); + static_assert(std::is_same_v(ps)), decltype(ps.i)&>); +} + +TEST(field_reflection, to_tuple) +{ + auto s = my_struct1{}; + auto& sr = s; + const auto& scr = s; + + auto t = to_tuple(s); + EXPECT_EQ(std::get<0>(t), s.i); + EXPECT_EQ(std::get<1>(t), s.d); + EXPECT_EQ(std::get<2>(t), s.hello); + EXPECT_EQ(std::get<3>(t), s.arr); + EXPECT_EQ(std::get<4>(t), s.map); + EXPECT_NE(&std::get<0>(t), &s.i); + EXPECT_NE(&std::get<1>(t), &s.d); + EXPECT_NE(&std::get<2>(t), &s.hello); + EXPECT_NE(&std::get<3>(t), &s.arr); + EXPECT_NE(&std::get<4>(t), &s.map); + + auto tr = to_tuple(sr); + EXPECT_EQ(std::get<0>(tr), s.i); + EXPECT_EQ(std::get<1>(tr), s.d); + EXPECT_EQ(std::get<2>(tr), s.hello); + EXPECT_EQ(std::get<3>(tr), s.arr); + EXPECT_EQ(std::get<4>(tr), s.map); + EXPECT_NE(&std::get<0>(tr), &s.i); + EXPECT_NE(&std::get<1>(tr), &s.d); + EXPECT_NE(&std::get<2>(tr), &s.hello); + EXPECT_NE(&std::get<3>(tr), &s.arr); + EXPECT_NE(&std::get<4>(tr), &s.map); + + auto tcr = to_tuple(scr); + EXPECT_EQ(std::get<0>(tcr), s.i); + EXPECT_EQ(std::get<1>(tcr), s.d); + EXPECT_EQ(std::get<2>(tcr), s.hello); + EXPECT_EQ(std::get<3>(tcr), s.arr); + EXPECT_EQ(std::get<4>(tcr), s.map); + EXPECT_NE(&std::get<0>(tcr), &s.i); + EXPECT_NE(&std::get<1>(tcr), &s.d); + EXPECT_NE(&std::get<2>(tcr), &s.hello); + EXPECT_NE(&std::get<3>(tcr), &s.arr); + EXPECT_NE(&std::get<4>(tcr), &s.map); + + auto trr = to_tuple(std::move(s)); + auto s2 = my_struct1{}; + EXPECT_EQ(std::get<0>(trr), s2.i); + EXPECT_EQ(std::get<1>(trr), s2.d); + EXPECT_EQ(std::get<2>(trr), s2.hello); + EXPECT_EQ(std::get<3>(trr), s2.arr); + EXPECT_EQ(std::get<4>(trr), s2.map); +} + +TEST(field_reflection, for_each_field) +{ + auto s1_a = my_struct1{}; + auto s1_b = my_struct1{}; + for_each_field(s1_a, [](auto&) {}); + for_each_field(s1_a, [](std::string_view, auto&) {}); + for_each_field(s1_a, s1_b, [](auto&, auto&) {}); + for_each_field(s1_a, s1_b, [](std::string_view, auto&, auto&) {}); + + auto s3_a = my_struct3{}; + auto s3_b = my_struct3{}; + for_each_field(s3_a, [](auto&) {}); + for_each_field(s3_a, s3_b, [](auto&, auto&) {}); + + auto s4_a = my_struct4{}; + auto s4_b = my_struct4{}; + for_each_field(s4_a, [](auto&) {}); + for_each_field(s4_a, [](std::string_view, auto&) {}); + for_each_field(s4_a, s4_b, [](auto&, auto&) {}); + for_each_field(s4_a, s4_b, [](std::string_view, auto&, auto&) {}); +} +// NOLINTEND