From 298fc66925471fa3e09dce904c5f6f35ea942cf2 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Tue, 23 Aug 2022 21:33:29 +0200 Subject: c++: add param pack, SFINAE/enable_if example --- src/development/c++.md | 17 +++++++ src/development/c++/.clang-format | 104 ++++++++++++++++++++++++++++++++++++++ src/development/c++/meta.cc | 34 +++++++++++++ src/development/c++/meta2.cc | 85 +++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 src/development/c++/.clang-format create mode 100644 src/development/c++/meta.cc create mode 100644 src/development/c++/meta2.cc (limited to 'src/development') diff --git a/src/development/c++.md b/src/development/c++.md index d9fbbda..4ce1538 100644 --- a/src/development/c++.md +++ b/src/development/c++.md @@ -10,3 +10,20 @@ auto foo = bar(); typename decltype(foo)::_; ``` +## Variadic templates ([parameter pack][parameter-pack]) + +```cpp +{{#include c++/meta.cc:3:}} +``` + +## [SFINAE][sfinae] example ([enable_if][enable-if]) + +```cpp +{{#include c++/meta2.cc:3:}} + +``` + +[gist-strict-asliasing]: https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8 +[parameter-pack]: https://en.cppreference.com/w/cpp/language/parameter_pack +[enable-if]: https://en.cppreference.com/w/cpp/types/enable_if +[sfinae]: https://en.cppreference.com/w/cpp/language/sfinae diff --git a/src/development/c++/.clang-format b/src/development/c++/.clang-format new file mode 100644 index 0000000..3cfb373 --- /dev/null +++ b/src/development/c++/.clang-format @@ -0,0 +1,104 @@ +# dotfiles -- clang-format +# author: johannst +# doc : https://clang.llvm.org/docs/ClangFormatStyleOptions.html + +Language: Cpp +Standard: Auto + +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakConstructorInitializersBeforeComma: false +BreakInheritanceList: BeforeColon +BreakBeforeInheritanceComma: false +BreakStringLiterals: true +ColumnLimit: 100 +CompactNamespaces: true +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +IncludeBlocks: Preserve +# Could use `IncludeCategories` to define rules for includes +IndentCaseLabels: true +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Never diff --git a/src/development/c++/meta.cc b/src/development/c++/meta.cc new file mode 100644 index 0000000..e674cfd --- /dev/null +++ b/src/development/c++/meta.cc @@ -0,0 +1,34 @@ +// Copyright (C) 2022 johannst + +#include + +// Base case with one parameter. +template +void show_int() { + printf("%d\n", P); +} + +// General case with at least two parameters, to disambiguate from base case. +template +void show_int() { + printf("%d, ", P0); + show_int(); +} + +// Base case with one parameter. +template +void show(const T& t) { + std::cout << t << '\n'; +} + +// General case with at least two parameters, to disambiguate from base case. +template +void show(const T0& t0, const T1& t1, const Types&... types) { + std::cout << t0 << ", "; + show(t1, types...); +} + +int main() { + show_int<1, 2, 3, 4, 5>(); + show(1, 1.0, "foo", 'a'); +} diff --git a/src/development/c++/meta2.cc b/src/development/c++/meta2.cc new file mode 100644 index 0000000..4c1194f --- /dev/null +++ b/src/development/c++/meta2.cc @@ -0,0 +1,85 @@ +// Copyright (C) 2022 johannst + +#include +#include + +// Helper meta fns. + +template +using enable_if_bool = std::enable_if_t; + +template +using disable_if_bool = std::enable_if_t; + +template +using has_dst = std::integral_constant::value>; + +// Template meta programming invoke machinery. + +namespace impl { + // Invoke an OPERATION which *USES* a context. + template class Op, typename... P, + enable_if_bool::HasCtx> = true> + typename Op::Return Invoke(const Ctx& C, P... params) { + return Op()(C, params...); + } + + // Invoke an OPERATION which uses *NO* context. + template class Op, typename... P, + disable_if_bool::HasCtx> = true> + typename Op::Return Invoke(const Ctx&, P... params) { + return Op()(params...); + } +} // namespace impl + +// Invoke an OPERATION which *HAS* a DESTINATION with arbitrary number of arguments. +template class Op, typename... P, + enable_if_bool>> = true> +void Invoke(const Ctx& C, P... params) { + std::cout << "Invoke " << Op::Name << '\n'; + typename Op::Return R = impl::Invoke(C, params...); + std::cout << "returned -> " << R << '\n'; +} + +// Invoke an OPERATION which has *NOT* a DESTINATION with arbitrary number of arguments. +template class Op, typename... P, + disable_if_bool>> = true> +void Invoke(const Ctx& C, P... params) { + std::cout << "Invoke " << Op::Name << " without destination." << '\n'; + impl::Invoke(C, params...); +} + +// Custom context. + +struct Ctx { + void out(const char* s, unsigned v) const { printf("%s%x\n", s, v); } +}; + +// Operations to invoke. + +template +struct OpA { + using HasCtx = std::false_type; + using Return = int; + static constexpr const char* const Name = "OpA"; + + constexpr Return operator()(int a, int b) const { return a + b; } +}; + +template +struct OpB { + using HasCtx = std::true_type; + using Return = void; + static constexpr const char* const Name = "OpB"; + + Return operator()(const Ctx& C, unsigned a) const { C.out("a = ", a); } +}; + +int main() { + Ctx C; + + Invoke(C, 1, 2); + Invoke(C, 0xf00du); + + return 0; +} -- cgit v1.2.3