aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/development
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2022-08-23 21:33:29 +0200
committerJohannes Stoelp <johannes.stoelp@gmail.com>2022-08-23 21:33:29 +0200
commit298fc66925471fa3e09dce904c5f6f35ea942cf2 (patch)
treedf9e3e430bd80f87dce25e12a926db54e91325ce /src/development
parent8018375d79d74f2911c335337722a719cf87c72e (diff)
downloadnotes-298fc66925471fa3e09dce904c5f6f35ea942cf2.tar.gz
notes-298fc66925471fa3e09dce904c5f6f35ea942cf2.zip
c++: add param pack, SFINAE/enable_if example
Diffstat (limited to 'src/development')
-rw-r--r--src/development/c++.md17
-rw-r--r--src/development/c++/.clang-format104
-rw-r--r--src/development/c++/meta.cc34
-rw-r--r--src/development/c++/meta2.cc85
4 files changed, 240 insertions, 0 deletions
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 <iostream>
+
+// Base case with one parameter.
+template<int P>
+void show_int() {
+ printf("%d\n", P);
+}
+
+// General case with at least two parameters, to disambiguate from base case.
+template<int P0, int P1, int... Params>
+void show_int() {
+ printf("%d, ", P0);
+ show_int<P1, Params...>();
+}
+
+// Base case with one parameter.
+template<typename T>
+void show(const T& t) {
+ std::cout << t << '\n';
+}
+
+// General case with at least two parameters, to disambiguate from base case.
+template<typename T0, typename T1, typename... Types>
+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 <iostream>
+#include <type_traits>
+
+// Helper meta fns.
+
+template<typename T>
+using enable_if_bool = std::enable_if_t<T::value, bool>;
+
+template<typename T>
+using disable_if_bool = std::enable_if_t<!T::value, bool>;
+
+template<typename T>
+using has_dst = std::integral_constant<bool, !std::is_same<typename T::Return, void>::value>;
+
+// Template meta programming invoke machinery.
+
+namespace impl {
+ // Invoke an OPERATION which *USES* a context.
+ template<typename Ctx, template<typename> class Op, typename... P,
+ enable_if_bool<typename Op<Ctx>::HasCtx> = true>
+ typename Op<Ctx>::Return Invoke(const Ctx& C, P... params) {
+ return Op<Ctx>()(C, params...);
+ }
+
+ // Invoke an OPERATION which uses *NO* context.
+ template<typename Ctx, template<typename> class Op, typename... P,
+ disable_if_bool<typename Op<Ctx>::HasCtx> = true>
+ typename Op<Ctx>::Return Invoke(const Ctx&, P... params) {
+ return Op<Ctx>()(params...);
+ }
+} // namespace impl
+
+// Invoke an OPERATION which *HAS* a DESTINATION with arbitrary number of arguments.
+template<typename Ctx, template<typename> class Op, typename... P,
+ enable_if_bool<has_dst<Op<Ctx>>> = true>
+void Invoke(const Ctx& C, P... params) {
+ std::cout << "Invoke " << Op<Ctx>::Name << '\n';
+ typename Op<Ctx>::Return R = impl::Invoke<Ctx, Op>(C, params...);
+ std::cout << "returned -> " << R << '\n';
+}
+
+// Invoke an OPERATION which has *NOT* a DESTINATION with arbitrary number of arguments.
+template<typename Ctx, template<typename> class Op, typename... P,
+ disable_if_bool<has_dst<Op<Ctx>>> = true>
+void Invoke(const Ctx& C, P... params) {
+ std::cout << "Invoke " << Op<Ctx>::Name << " without destination." << '\n';
+ impl::Invoke<Ctx, Op>(C, params...);
+}
+
+// Custom context.
+
+struct Ctx {
+ void out(const char* s, unsigned v) const { printf("%s%x\n", s, v); }
+};
+
+// Operations to invoke.
+
+template<typename Ctx>
+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<typename Ctx>
+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<Ctx, OpA>(C, 1, 2);
+ Invoke<Ctx, OpB>(C, 0xf00du);
+
+ return 0;
+}