The switch statement in C/C is a powerful control flow mechanism that allows for efficient branching based on integer values. However, it is often desirable to switch on non-integer values, such as strings or enums. This presents a challenge as switch statements only accept integer arguments.
One traditional approach to handling non-integer switch arguments is to use a sequence of if statements:
if( str == "foo" ) ... else if( str == "bar" ) ... else ...
However, this approach is inefficient as it requires linear time complexity (O(n)) for n cases. A more efficient solution is to represent the non-integer values as integers, either using maps or nested ifs. However, these approaches can be complex and error-prone.
Using macros, it is possible to implement an unrolled binary search at compile time, allowing for a fast and syntax-friendly approach:
#define NEWMATCH #define MATCH("asd") some c++ code #define MATCH("bqr") ... the buffer for the match is in _buf #define MATCH("zzz") ... user.YOURSTUFF #define ENDMATCH(xy_match)
This macro will generate a function that takes a string as input and returns a boolean, implementing a binary search through the specified cases.
In C 11, lambdas and initializer lists offer a more elegant and concise approach:
template<typename KeyType, typename FunPtrType> void switchStatement(const KeyType& value, std::initializer_list<std::pair<const KeyType, FunPtrType>> sws) { std::lower_bound(sws.begin(), sws.end(), value, [&](const auto& a, const auto& b) { return a.first < b.first; }); if (r != sws.end() && !cmp(val, *r)) { r->second(); } // else: not found }
int main() { switchStatement<const char*, void(*())>("ger", { { "asdf", []{ printf("0\n"); } }, { "bde", []{ printf("1\n"); } }, { "ger", []{ printf("2\n"); } }, }); return 0; }
In modern C , C 11 metaprogramming techniques can be utilized to create a compile-time trie, an advanced data structure that can efficiently handle unsorted case branches:
#include <smile/cttrie/cttrie.h> using namespace smile::cttrie; // Define cases as string literals trie<true, void()> s = {"foo", "bar"}; int main() { // Switch on a string s.switch_on("foo", []() { std::cout << "foo" << std::endl; }); return 0; }
The above is the detailed content of How Can I Efficiently Implement a Switch Statement with Non-Integer Arguments in C/C ?. For more information, please follow other related articles on the PHP Chinese website!