diff options
author | johannst <johannst@users.noreply.github.com> | 2022-08-23 19:33:47 +0000 |
---|---|---|
committer | johannst <johannst@users.noreply.github.com> | 2022-08-23 19:33:47 +0000 |
commit | f647a8c45dda58078c86a96c68ae00ea1c69a222 (patch) | |
tree | 22bd878bdf2eb523a8c057ac6ba3b2377031ad6e /development/c++/meta2.cc | |
parent | 88bc7f1209668aa64b2f110121f6f4a2506b9d0c (diff) | |
download | notes-f647a8c45dda58078c86a96c68ae00ea1c69a222.tar.gz notes-f647a8c45dda58078c86a96c68ae00ea1c69a222.zip |
deploy: 298fc66925471fa3e09dce904c5f6f35ea942cf2
Diffstat (limited to 'development/c++/meta2.cc')
-rw-r--r-- | development/c++/meta2.cc | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/development/c++/meta2.cc b/development/c++/meta2.cc new file mode 100644 index 0000000..4c1194f --- /dev/null +++ b/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; +} |