online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
#include <array> #include <iostream> #include <tuple> using namespace std; // Helper for Shorthand Option 1 (below) template<typename Singleton> Singleton* singleton; // Helper to store string literals at compile-time template<typename ParentDispatcher> struct Tag { using Parent = ParentDispatcher; const char* name; }; // --------------------------------- // DISPATCHER: // --------------------------------- // Call different functions at compile-time based upon // a compile-time string literal. // --------------------------------- template<auto& nameArray, typename FuncTuple> struct Dispatcher { FuncTuple _funcs; using DispatcherTag = Tag<Dispatcher>; template<size_t nameIndex> static constexpr DispatcherTag TAG = {nameArray[nameIndex]}; static constexpr DispatcherTag INVALID_TAG = {}; Dispatcher(const FuncTuple& funcs) : _funcs(funcs) { singleton<Dispatcher> = this; } template<size_t nameIndex = 0> static constexpr auto& tag(string_view name) { if(name == nameArray[nameIndex]) { return TAG<nameIndex>; } else { if constexpr (nameIndex+1 < nameArray.size()) { return tag<nameIndex+1>(name); } else { return INVALID_TAG; } } } static constexpr size_t index(string_view name) { for(size_t nameIndex = 0; nameIndex < nameArray.size(); ++nameIndex) { if(name == nameArray[nameIndex]) { return nameIndex; } } return nameArray.size(); } constexpr auto& operator()(const char* name) const { return tag(name); } template<auto& tag, typename... Args> auto call(Args... args) const { static constexpr size_t INDEX = index(tag.name); static constexpr bool VALID = INDEX != nameArray.size(); static_assert(VALID, "Invalid tag."); return get<INDEX*VALID>(_funcs)(args...); } }; template<auto& nameArray, typename FuncTuple> auto makeDispatcher(const FuncTuple& funcs) { return Dispatcher<nameArray, FuncTuple>(funcs); } // --------------------------------- // SHORTHAND: OPTION 1 // --------------------------------- // Use a singleton pattern and a helper to let a tag be associated with a // specific dispatcher, so that the call-site need not specify dispatcher twice // --------------------------------- template<auto& tag, typename... Args> auto call(Args... args) { using Tag = remove_reference_t<decltype(tag)>; using ParentDispatcher = typename Tag::Parent; static auto dispatcher = singleton<ParentDispatcher>; return dispatcher->template call<tag>(args...); } // --------------------------------- // SHORTHAND: OPTION 2 // --------------------------------- // Use a string template user-defined literal operator to shorten call-site syntax // gcc supports this as an extension implementing proposal N3599 (standardized in C++20) // If warnings occur, try pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template" // --------------------------------- // Need characters to be in contiguous memory on the stack (not NTTPs) for TAG_FROM_LITERAL template<char... name> constexpr char NAME_FROM_LITERAL[] = {name..., '\0'}; // Don't need to specify Dispatcher with user-defined literal method; will use dispatcher.check<>() struct TagFromLiteral {}; // Need to have a constexpr variable with linkage to use with dispatcher.check<>() template<char... name> constexpr Tag<TagFromLiteral> TAG_FROM_LITERAL = {NAME_FROM_LITERAL<name...>}; // Create a constexpr variable with linkage for use with dispatcher.check<>(), via "MyTag"_TAG template<typename Char, Char... name> constexpr auto& operator"" _TAG() { return TAG_FROM_LITERAL<name...>; } // --------------------------------- // SHORTHAND: OPTION 3 // --------------------------------- // Use a macro so the call-site need not specify dispatcher twice // --------------------------------- #define DISPATCH(dispatcher, name) dispatcher.call<dispatcher(name)> // --------------------------------- // COMMON: TEST FUNCTIONS // --------------------------------- bool testFunc1(int) { cout << "testFunc1" << endl; } bool testFunc2(float) { cout << "testFunc2" << endl; } bool testFunc3(double) { cout << "testFunc3" << endl; } static constexpr auto funcs = make_tuple(&testFunc1, &testFunc2, &testFunc3); static constexpr auto names = array{"one", "two", "three"}; int main() { // Create a test dispatcher auto dispatcher = makeDispatcher<names>(funcs); // LONG-HAND: call syntax: a bit verbose, but operator() helps dispatcher.call<dispatcher("one")>(1); // SHORTHAND OPTION 1: non-member helper, singleton maps back to dispatcher call<dispatcher("one")>(1); // SHORTHAND OPTION 2: gcc extension for string UDL templates (C++20 standardizes this) dispatcher.call<"one"_TAG>(1); // SHORHAND OPTION 3: Macro DISPATCH(dispatcher, "one")(1); return 0; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue