diff --git a/README.adoc b/README.adoc index 4a85e93..57b31af 100644 --- a/README.adoc +++ b/README.adoc @@ -20224,10 +20224,6 @@ Programs under link:userland/cpp/[] are examples of https://en.wikipedia.org/wik **** http://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets ** `virtual` and polymorphism *** link:userland/cpp/virtual.cpp[] -* templates -** link:userland/cpp/template.cpp[]: basic example -** link:userland/cpp/template_class_with_static_member.cpp[]: https://stackoverflow.com/questions/3229883/static-member-initialization-in-a-class-template -** link:userland/cpp/if_constexpr.cpp[]: C++17 `if constexpr`: https://stackoverflow.com/questions/12160765/if-else-at-compile-time-in-c/54647315#54647315 * iostream ** link:userland/cpp/copyfmt.cpp[]: `std::copyfmt` restores stream state, see also: https://stackoverflow.com/questions/12560291/set-back-default-floating-point-print-precision-in-c/53673686#53673686 * fstream @@ -20511,6 +20507,18 @@ https://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-sta http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf +[[cpp-templates]] +==== C++ templates + +* link:userland/cpp/template.cpp[]: basic example +* link:userland/cpp/template_class_with_static_member.cpp[]: https://stackoverflow.com/questions/3229883/static-member-initialization-in-a-class-template + +===== SFINAE + +https://en.cppreference.com/w/cpp/language/sfinae + +Not possible to do the typecheck automatically without explicitly giving type constraints: https://stackoverflow.com/questions/53441832/sfinae-automatically-check-that-function-body-compiles-without-explicit-constrai + [[cpp-type-casting]] ==== C++ type casting @@ -20521,6 +20529,8 @@ https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast- [[cpp-compile-time-magic]] ==== C++ compile time magic +* link:userland/cpp/if_constexpr.cpp[]: C++17 `if constexpr`: https://stackoverflow.com/questions/12160765/if-else-at-compile-time-in-c/54647315#54647315 + [[cpp-decltype]] ===== C++ `decltype` diff --git a/userland/cpp/if_constexpr.cpp b/userland/cpp/if_constexpr.cpp index 3d9ef68..a0afc0d 100644 --- a/userland/cpp/if_constexpr.cpp +++ b/userland/cpp/if_constexpr.cpp @@ -1,5 +1,4 @@ -// https://cirosantilli.com/linux-kernel-module-cheat#cpp - +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-compile-time-magic #if __cplusplus >= 201703L #include diff --git a/userland/cpp/sfinae.cpp b/userland/cpp/sfinae.cpp new file mode 100644 index 0000000..b6cc349 --- /dev/null +++ b/userland/cpp/sfinae.cpp @@ -0,0 +1,40 @@ +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-templates + +#include + +struct HasMyfunc { + int myfunc() const { return 1; } +}; +struct NoHasMyfunc { + int myfunc2() const { return 11; } +}; + +// int() is the actual return type. +// t.myfunc() checks that t has method myfunc(). +// The decltype does not have multiple arguments, just a single comma separated expression: +// https://stackoverflow.com/questions/16044514/what-is-decltype-with-two-arguments +// Syntax breakdown: +// https://medium.com/@mortificador/choose-between-different-implementations-depending-on-type-properties-at-compile-time-in-c-68e3fd5cd2f8 +template +auto template_func(const T& t) -> + decltype(t.myfunc(), int()) +{ + return t.myfunc(); +} + +template +auto template_func(const T& t) -> + decltype(t.myfunc2(), int()) +{ + return t.myfunc2(); +} + +int main() { + // Hello world example. + // The correct template is used for the type that has each different method. + // If we didn't specify constraints for each template type, C++ would blow up + // with multiple possible functions: + // https://stackoverflow.com/questions/53441832/sfinae-for-function-body + assert(template_func(HasMyfunc()) == 1); + assert(template_func(NoHasMyfunc()) == 11); +} diff --git a/userland/cpp/template.cpp b/userland/cpp/template.cpp index 7f7c038..8068df4 100644 --- a/userland/cpp/template.cpp +++ b/userland/cpp/template.cpp @@ -1,4 +1,4 @@ -// https://cirosantilli.com/linux-kernel-module-cheat#cpp +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-templates #include diff --git a/userland/cpp/template_class_with_static_member.cpp b/userland/cpp/template_class_with_static_member.cpp index 33f3a8d..a286689 100644 --- a/userland/cpp/template_class_with_static_member.cpp +++ b/userland/cpp/template_class_with_static_member.cpp @@ -1,4 +1,4 @@ -// https://cirosantilli.com/linux-kernel-module-cheat#cpp +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-templates #include