Request Short Link
C++ 98
C++ 11
C++ 14
C++ 17
C++ 20
C++ 23
C++ 2c
for-loops as while-loops
array subscription
Show all implicit casts
Show all template parameters of a CallExpr
Use libc++
Transform std::initializer_list
Show noexcept internals
Show padding information
Show coroutine transformation
Show C++ to C transformation
Show object lifetime
Default
15
18
20
22
26
More
GitHub
Patreon
Issues
About
Policies
Examples
C++ Insights @ YouTube
Settings
Version
Join now: C++ Self Study + 1:1 Coaching
×
Made by
Andreas Fertig
Powered by
Flask
and
CodeMirror
Source:
#include <cstddef> #include <utility> #include <algorithm> #include <string> #include <vector> #include <iostream> namespace lib { namespace internal { template <template <std::size_t> typename F, std::size_t... Indices> auto GetCompileSwitchCallbackImpl(std::index_sequence<Indices...>, std::size_t switch_idx) { decltype(&F<0>::CallbackFn) result = nullptr; std::initializer_list<std::size_t>( {(switch_idx == Indices ? (result = &F<Indices>::CallbackFn), std::size_t() : std::size_t())...}); return result; } } // namespace internal // Provides a compile-time functionality that emulates the C/C++ Switch-Case // operator. // // If `switch_idx <= kMaxSwitchIdx`, this function returns a pointers to the // `F<kIndex>::CallbackFn` static method where `kIndex` equals to `switch_idx`. // // If `switch_idx > kMaxSwitchIdx`, this function returns `nullptr`. // // Requirements: // // `F` must be a template class/struct with one `std::size_t` template argument. // `F` must have a static method called `CallbackFn`. The signature of the // method must be the same for all instantiations. template <std::size_t kMaxSwitchIdx, template <std::size_t> typename F> auto GetCompileSwitchCallback(std::size_t switch_idx) { return internal::GetCompileSwitchCallbackImpl<F>( std::make_index_sequence<kMaxSwitchIdx + 1>(), switch_idx); } } // namespace lib std::vector<std::string>& GetStrCollection() { static std::vector<std::string> str_collection; return str_collection; } // Returns the index of `str` in `GetStrCollection()`. If not present, adds // `str` into the collection and generates a new index. std::size_t FindOrInsertStr(const std::string& str) { auto& str_collection = GetStrCollection(); auto it = std::find(str_collection.begin(), str_collection.end(), str); if (it == str_collection.end()) { str_collection.push_back(str); return str_collection.size() - 1; } else { return it - str_collection.begin(); } } using GreetFnPtr = void (*)(); template <std::size_t kIndex> struct GreetFnPtrHelper { static void CallbackFn() { std::cout << "Hello, " << GetStrCollection()[kIndex] << "!" << std::endl; } }; GreetFnPtr CreateGreetFnPtrByName(const std::string& name) { static constexpr std::size_t kMaxNumUniqueNames = 100; return lib::GetCompileSwitchCallback<kMaxNumUniqueNames, GreetFnPtrHelper>( FindOrInsertStr(name)); } void DemoFunctionPointers() { std::string alice_name = "Alice"; std::string bob_name = "Bob"; GreetFnPtr alice_greet = CreateGreetFnPtrByName(alice_name); GreetFnPtr bob_greet = CreateGreetFnPtrByName(bob_name); GreetFnPtr random_greet = (rand() & 16384) ? alice_greet : bob_greet; alice_greet(); // Prints "Hello, Alice!" bob_greet(); // Prints "Hello, Bob!" random_greet(); // Prints either "Hello, Alice!" or "Hello, Bob!" }
Insight:
Console: