运行阶段双分派

原创 2007年09月20日 18:44:00

如果你想在运行阶段分派,你将避免暴力手段,因为简单的dynamic_cast底层一样消耗我们的效率。

pair是个不错的东西,它可以把两个东西当成一个用。pair两个类型作为索引可以获得双分派的目标函数,这是最朴素的想法:

template    <class BaseLhs,class BaseRhs,typename ResultType>
class    BasicDispatcher
...{
    typedef    pair
<OrderedTypeInfo,OrderedTypeInfo>    KeyType;
        
//pair是一个强有力的工具
    typedef    ResultType    (*CallbackType)(BaseLhs&,BaseRhs&);
    typedef    CallbackType    MappedType;
    map
<KeyType,MappedType>    MapType;
    MapType        callbackMap_;
}
;

模板化的双BasicDispatcher像这样:

template
<
    
class    BaseLhs,
    
class    BaseRhs,
    typename    ResultType,
    typename    CallbackType    
= ResultType    (*)(BaseLhs&,BaseRhs&)
>
class    BasicDispatcher
...{
    typedef    pair
<TypeInfo,TypeInfo>        KeyType;
    typedef    CallbackType                MappedType;
    typedef    AssocVector
<KeyType,MappedType>    MapType;
    MapType    callbackMap_;

public:
    template    
<class SomeLhs,class SomeRhs>
    
void    Add(CallbackType    fun)
    
...{
        
const    KeyType    key(typeid(SomeLhs),typeid(SomeRhs));
        callbackMap_[key]    
= fun;
    }

    
    ResultType    Go(BaseLhs
& lhs,BaseRhs& rhs)
    
...{
        MapType::iterator    i    
= callbackMap_.find(KeyType(typeid(lhs),typeid(rhs)));
        
if (i == callbackMap_.end())
        
...{
            
throw    "fun not found";
        }

        
return    (i->second)(lhs,rhs);
    }

}
;

使用起来像这样: 

class MyBase;
class MyA;
class MyB;
typedef    BasicDispatcher
<MyBase,MyBase,void>    Dispatcher;
void    DoSmThing(MyBase& lhs,MyBase rhs)
...{
    MyA
&    ra    = dynamic_cast<MyA&>(lhs);
    MyB
&    rb    = dynamic_cast<MyB&>(rhs);
    
//...
}

Dispatcher    disp;
disp.Add
<MyA,MyB>(DoSmThing);

这已经足够好了,但是还是有问题,你只能对已注册的类型进行操作。对于继承的情况,这需要客户转型,这是非常危险和我们不愿看到的,于是有了trampoline的解决方案,它其实是对上述BasicDispatcher的一个包装,但是不需要用户处理转型。

template    <class BaseLhs,class BaseRhs,typename ResultType,class BDispatcher = BasicDispatcher>
class FnDispatcher
...{
    BDispatcher
<BaseLhs,BaseRhs,ResultType>    backEnd_;
public:
    template    
<class ConcretLhs,class ConcretRhs,ResultType (*callback)(ConcretLhs&,ConcretRhs)>
    
void    Add()
    
...{
        
struct Local 
        
...{
            
static    ResultType    Trampoline(BaseLhs& lhs,BaseRhs& rhs)
            
...{
                
return    callback(dynamic_cast<ConcretLhs&>(lhs),dynamic_cast<ConcretRhs&>(rhs));
            }

        }
;
        
return    backEnd_.Add(ConcretRhs,ConcretLhs>(&Local::Trampoline));
            
//这太美妙了
    }

}
;

对于对称的问题,也不用在调用的时候进行判断,我们多提供一个方法就可以了:

template    <class ConcretLhs,class ConcretRhs,ResultType (*callback)(ConcretLhs&,ConcretRhs),bool symmetric>
void    Add()
...{
    
struct Local 
    
...{
        
static    ResultType    Trampoline(BaseLhs& lhs,BaseRhs& rhs)
        
...{
            
return    callback(dynamic_cast<ConcretLhs&>(lhs),dynamic_cast<ConcretRhs&>(rhs));
        }

    }
;
    Add
<ConcretLhs,ConcretRhs>(&Local::Trampoline);
    
if (symmetric)
    
...{
        Add
<ConcretRhs,ConcretLhs>(&Local::Trampoline);
    }

}

我把这个理解为双分派的map解决方案,你也可以直接使用Loki库享用这个功能,但是了解这底层的细节有助于你处理类似问题的时候获得一个想法,而不是使用现成的东西。Loki给了你一个基本的框架可以使用模仿,但是遇到问题借助它的思想解决问题的情况也非常或者说更普遍,这是我现在使用Loki的感觉,所以更多的时候我想多了解一点这底层的东西,Andrei大脑里的东西。

OpenResty 执行阶段的概念和用途

主要还是 Nginx 的执行阶段知识了,都是因为 OR 才会那么深刻, 它有些自己的阶段。 主要还是参照 春哥的 Nginx 教程 请多读几遍,如果不清楚nginx的执行阶段就无法充分利用 openr...
  • lzz957748332
  • lzz957748332
  • 2017年01月12日 01:19
  • 1222

mapreduce运行的5个阶段

mapreduce shuffle运行过程
  • chenzhikaida
  • chenzhikaida
  • 2015年10月26日 13:17
  • 2308

nginx-lua 运行阶段

Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是{ post-read、[Nginx 读取并解析完请求头(request headers)之后就立即开始运行 server-re...
  • fb408487792
  • fb408487792
  • 2016年12月13日 15:27
  • 1079

VB在程序运行阶段建立MDB数据库文件

  • 2010年07月13日 11:21
  • 13KB
  • 下载

用代码在程序运行阶段建立MDB数据库文件(4KB)

  • 2006年02月23日 09:05
  • 3KB
  • 下载

73用代码在程序运行阶段建立MDB数据库文件

  • 2011年04月02日 03:28
  • 13KB
  • 下载

第三阶段-tensorflow项目之图像image相关--tensorflow搭建CNNs 之CIFAR-10多个GPU运行

本blog面向有TensorFlow经验的用户,并有机器学习方面的专业知识和经验。1,Overview概述CIFAR-10分类是机器学习中常见的标准基础问题。 问题是分类10个类别的RGB 32x32...
  • jk981811667
  • jk981811667
  • 2018年01月03日 10:32
  • 53

nginx-lua 运行阶段

Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是
  • uisoul
  • uisoul
  • 2017年03月15日 18:46
  • 480

[笔记][Java7并发编程实战手册]3.6 并发阶段任务的运行phaser

[笔记][Java7并发编程实战手册]系列目录简介Phaser是一个更强大的、更复杂的同步辅助类,可以代替CyclicBarrier CountDownLatch的功能,但是比他们更强大。 Phas...
  • mr_zhuqiang
  • mr_zhuqiang
  • 2015年08月23日 16:54
  • 636

第一阶段-入门详细图文讲解tensorflow1.4 -(六)tensorflow运行机制MNIST

本篇blog目的:展示如何使用tensorflow训练和评估一个简单的前馈神经网络。a simple feed-forward neural network 。面向一些有经验的机器学习人员。使用的两个...
  • jk981811667
  • jk981811667
  • 2017年12月19日 14:41
  • 63
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:运行阶段双分派
举报原因:
原因补充:

(最多只允许输入30个字)