使用一些复杂的宏和模板魔法,可以在编译时得到一个展开的二分查找,而且语法很清晰--但是匹配("case")必须排序:fastmatch.h
NEWMATCH
MATCH("asd")
some c++ code
MATCH("bqr")
... the buffer for the match is in _buf
MATCH("zzz")
... user.YOURSTUFF
/*ELSE
optional
*/
ENDMATCH(xy_match)
这将生成(大致)一个函数bool xy_match(char *&_buf, T &user)
,因此必须位于外层级别。例如,使用以下方式调用:
xy_match("bqr",youruserdata);
而且,break
是隐式的,你不能fall-thru。这也没有过多的文档记录,抱歉。但你会发现,还有一些更多的用法,可以看一下。注意:仅在g++下测试过。
更新C++11:
Lambdas和初始化列表使事情变得更漂亮(不涉及宏!):
#include <utility>
#include <algorithm>
#include <initializer_list>
template <typename KeyType,typename FunPtrType,typename Comp>
void Switch(const KeyType &value,std::initializer_list<std::pair<const KeyType,FunPtrType>> sws,Comp comp) {
typedef std::pair<const KeyType &,FunPtrType> KVT;
auto cmp=[&comp](const KVT &a,const KVT &b){ return comp(a.first,b.first); };
auto val=KVT(value,FunPtrType());
auto r=std::lower_bound(sws.begin(),sws.end(),val,cmp);
if ( (r!=sws.end())&&(!cmp(val,*r)) ) {
r->second();
}
}
#include <string.h>
#include <stdio.h>
int main()
{
Switch<const char *,void (*)()>("ger",{
{"asdf",[]{ printf("0\n"); }},
{"bde",[]{ printf("1\n"); }},
{"ger",[]{ printf("2\n"); }}
},[](const char *a,const char *b){ return strcmp(a,b)<0;});
return 0;
}
那就这个意思。更完整的实现可以在这里找到:
switch.hpp。
2016年更新:编译时字典树
我对这个问题的最新解决方案使用了先进的c++11元编程,在编译时生成一个
搜索字典树。与以前的方法不同,这将很好地处理
未排序的情况分支/字符串;它们只需要是字符串文字。G++也允许对它们进行constexpr,但clang不允许(截至HEAD 3.9.0 / trunk 274233)。
在每个字典树节点中,利用开关语句来利用编译器的高级代码生成器。
完整的实现可在github上找到:
smilingthax/cttrie。
str=="foo"
的条件,这在C中无法工作)。我的翻译不会改变原意,只会尽量让内容更加通俗易懂。 - MSalters