开始的第一方案的查询时间达到了O(n),我们认为在类的数量比较少的时候是可行的。在进入了第二方案的时候,我们让查询速度时间缩短到了O(log(n)),如果我们要在这里更进一步的话,那就应该是O(1)了。在这里我们就继续推出这个所谓的常数时间方案。
在第二方案的时候,我们需要对数时间的比较来得到答案,如果是常数时间,那必须摒弃这种比较。参照前面的思路继续往下,前面的map如果改成hashtable应该就可以了,每次对key通用运算就得到了对应value(就是函数或者functor)而这里的key就是两个类型参数组成的pair。但是Hashtable带来了一定的复杂性和不稳定性。这里大名鼎鼎的Alex给出的更直接稳定的方案就是直接把每个类都添加进一个index,通过2个index在二维数组中找到对应的处理函数(或者Functor)。这里有一张文中的示意图:
可以看到如果以后的处理函数是Rectangle,Screen的话,我们就找1,1这个点。类似的如果处理Circle在Printer上打印的话,我们就找3,4这个点对应的函数。这个用空间换取时间的方案就是通过std::vector来实现的,下面就是具体的实现:
类的index不是固定的,或者说并不是在TypeList中的index,因为我们这里已经没有TypeList了。现在需要主动需要植入每个class里面,这也意味这原来非侵入式的平衡已经被打破了。每个类都需要申明这个宏。这里的Matrix通过std::vector来组织,存放的具体内容就是CallbackType,当前这个BasicFastDispatcher类和原来的BasicDispatcher平行,也就是说可以通过Policy来进行替换,成为其他FnDispatcher的新的back end。在这里的vector size的处理上有点小技巧,通过columns_来动态调整vector的size,而不是一上来就开出整个typelist长度的二维数组。同时也通过这个columns_来给classindex赋值。(注意这里的GetClassIndexStatic函数返回的一直是int&)。还有一点就是出错处理这里没有写出来,但是不像原来的hatcher可以有个类,这里都是对应的函数,所以一般我们会在这里抛出一个异常。
Okay,我们就把所有的三个方案就介绍了一遍,这里有一张图涵盖了对三种方式的特性的总结:
至此,我们对既有方案有一个全面的认识,从而为特定的case选择的时候也有章可循了。