使用boost的函数库实现通用switch-case/if..else选择器
在通信行业做事久了,经常发现在写的程序中,大量重复出现if..else..这种嵌套层次相当深的switch写法,所以就蒙生了自己写一个通用switcher的想法,把这种强耦合的写法隔离,所以就用了下面的实现
/*********************************************
* 通用选择器
* 1. 适配原始函数指针
* 2. 适配成员函数指针
* 3. 适配仿函数
* 4. 绑定函数
********************************************/
template <typename RESULT,
typename KEY,
typename PARA>
class switcher
{
private:
typedef boost::function <RESULT, PARA> FUNCTOR;
public:
void add_observer(KEY key, FUNCTOR func)
{
functorset.insert(make_pair(key, func));
}
RESULT match(KEY key, PARA para)
{
map <KEY, FUNCTOR> ::const_iterator iter;
iter = functorset.find(key);
if (iter != functorset.end())
{
static_cast <FUNCTOR> (iter-> second)(para);
}
}
private:
map <KEY, FUNCTOR> functorset;
};
bool some_function(const std::string& s)
{
std::cout < < s < < " This is really neat\n ";
return true;
}
class some_class
{
public:
bool some_function(const std::string& s)
{
std::cout < < s < < " This is also quite nice\n ";
return true;
}
};
class some_function_object
{
public:
bool operator()(const std::string& s)
{
std::cout < < s < <
" This should work, too, in a flexible solution\n ";
return true;
}
};
switcher <bool, int, string> myswitcher;
bool test(int number, string info)
{
return myswitcher.match(number, info);
}
int main(int argv, char** argc)
{
function1 <bool,const std::string&> f1(&some_function);
function1 <bool,const std::string&> f2(&some_class::some_function,&s);
function1 <bool,const std::string&> f3(boost::bind(&some_class::some_function,&s,_1));
some_function_object fso;
function1 <bool,const std::string&> f4(fso);
myswitcher.add_observer(0, f1);
myswitcher.add_observer(1, f2);
myswitcher.add_observer(2, f3);
myswitcher.add_observer(3, f4);
test(0, "call by f1 ");
}
文章还有不足之处,敬请大家指教,希望能和喜欢Boost库的朋友做做交流
[解决办法]
这个,需要做这么复杂吗?
switch用查表法实现是个基本常识,直接用map + boost的assign库map_list_of已经足够了。
[解决办法]
是哦.要么LZ谈谈, 相对比state, strategy模式有什么优势.
[解决办法]
如楼上所说,用表驱动的状态机来表示,代码只会变短。
[解决办法]
既然你用了状态机就应该明白它的表驱动表示法撒。
Map的算法效率是O(LogN),查表法可以是O(1),哪个效率好?
Map的绑定关系是一维的,而查表法是二维的,从逻辑上更为清晰,特别是使用嵌套状态的时候。
[解决办法]
局部代码乱,可以用重构的方法整理。整体代码乱,还不如推倒重来。
而且我觉得一开始就用Boost不是什么明智之举,与效率、维护都没什么直接关系。
[解决办法]
为什么忽视vtbl呢? C++自身就有表啊.
为什么忽视 < <设计模式> > 里的state, strategy模式这些模式呀?
我预计你们的方案一定是有更高的运行时效率 ? 有更好的扩展性 ?
解释下.谢谢.
[解决办法]
有bug
1. 没有返回值:
2. find()失败, 直接崩溃!
RESULT match(KEY key, PARA para)
{
map <KEY, FUNCTOR> ::const_iterator iter;
iter = functorset.find(key);
if (iter != functorset.end())
{
static_cast <FUNCTOR> (iter-> second)(para);
}
}
[解决办法]
好了. 大家没啥火气了, 再好好聊聊吧.
说实在的. 我觉得你这个类, 做做练习, 锻炼一下是挺好的. 但我不会将他作为正式的工程项目中的一部分.
1. 没有严格验证.
2. 相对来说比较复杂. 他要求项目组里的人要会用boost::function, boost::bind. 这个在当前有点要求过高.
3. 实现的效率不高. map的复杂度, 正如 BluntBlade 所说, O(logN), 比起O(1).效率低. 不过, 再怎么说, 这个case 不可能上百万条吧, 所以效率也许不在热点上也不是问题.
4. 只支持 单参 方法, 还不支持 返回值. 我有点接受不了. 不知道boost::signal怎么搞的.要研究呀.
5. 我们总是忽略惯用手法和成熟经验. 这在我的公司尤其如此, 过分强调创新, 忽略这样的事实, 成功的项目往往取决于采用的成熟库在整体代码中占的比重. 这也是我一看到这么个新东西的反感. 向你道个歉.
6. 面向对象的设计模式是反复应用反复实践的成熟理论. 并且, 当前有重构, 迭代这样的成熟工程理论支撑确保能小步走向目标. 因此, 相对而言, 我愿意采取这样的技术.
7. 我喜欢范型, 也愿意学习它, 但目前看下来在真实的项目中, 大规模实行, 目前还没有到时候.这要求一个团队的软件成熟度达到一定的层次才行的. 不压抑自己的技术欲望, 盲目的优化, 采用新技术, 给项目带来多少血的教训啊. 我自己也深有体会. 因此, 我常要清醒下自己, 切莫满负荷, 保持掌握里.
乱写一气, 莫怪~
[解决办法]
此帖收藏。。。
向楼上的牛人们学习。。。
弱弱的问一下, 楼上的牛牛们工作几年了 ??? 学习.....
------解决方案--------------------
第二点,什么是强侵入性设计。
强侵入性设计是指对使用者有很多要求,即使很多功能用户不需要使用也无法裁减和替代。
MFC已经被认为是强侵入性设计的典范,而ACE则是非侵入性设计的典范。
你现在的设计,要求用户差不多同时要掌握function、lambda、tuple。
如果不是因为要使用你这个设计,会有多少情况需要同时使用这么多比较高阶的东西。
而且,按你现在的设计,即使functor不需要参数,也得给个哑参。
[解决办法]
作为一个通用库的实现者,你不能假设用户需不需要支持异质functor,所以,functor的类型应该由用户作为模板参数传入,就如同我前面的代码,用户自己typedef任何东西为PROCESSOR。
相应地,你的add_observer接口应该把function去掉。
[解决办法]
boost::function 去不去各有各的好处
不去,可以把实现写在cpp里面
//hpp
void foo(boost::function x);
//cpp
void foo(boost::function x){
}