﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-qiezi的学习园地-随笔分类-asgard项目</title><link>http://www.cppblog.com/cpunion/category/59.html</link><description>AS/C/C++/D/Java/JS/Python/Ruby</description><language>zh-cn</language><lastBuildDate>Fri, 23 May 2008 09:10:28 GMT</lastBuildDate><pubDate>Fri, 23 May 2008 09:10:28 GMT</pubDate><ttl>60</ttl><item><title>为C＋＋实现一个IDL　（五）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/28/481.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Wed, 28 Sep 2005 14:57:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/28/481.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/481.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/28/481.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/481.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/481.html</trackback:ping><description><![CDATA[本篇没什么清晰的目的，只是解释一下前面的几个问题，并提出一些新的目标。<BR><BR>在“asgard项目遗留问题”中，我简单提到了几个问题，并且想了一些解决方案。<BR><BR>其中，最首要解决的是第2条“服务对象的大小”和第5条“全局元信息”，这2条将影响到调用机制、call对象的生成。一个调用将生成一个call对象，由线程池来处理，同步调用将由异步调用来模拟。<BR><BR>在call对象中，保存了所有in/out参数的包装对象。当处理同步调用时，由于out参数可能是一个栈上对象（或简单类型，这里统称对象），所以需要另一个包装类——outret模板类，它保存out参数的引用。<BR><BR>当同步调用发生时，生成一个call对象（当然out参数的引用已经包含在里面），把这个call对象交给线程池处理，调用的线程阻塞等待调用结束后被唤醒，这就是所谓的异步调用模拟同步调用。由于异步调用被包装起来了，所以在调用者看来跟同步调用没什么区别。当然这个动作并非必要，完全可以不使用模拟，而采用真正的同步调用，只是看到ICE是这么实现的，心痒痒而已。<BR><BR><BR>asgard的目标是把现有的系统功能包装成为服务，所以在通用方面我考虑得比较多。<BR><BR>比如服务端要开放下面这样一个服务：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">service&nbsp;StringService<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;strcat;<BR>&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">uint</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;strncat;<BR>};</SPAN></DIV><BR>并且把C标准库中的strcat和strncat作为这2个方法的实现。<BR><BR>看一下存在哪些问题？<BR><BR>1、函数第1个参数如果直接映射为string，在服务端将出现缓冲区溢出。<BR><BR>2、C标准库中的strcat返回值是一个指针，它指向strcat的第一个参数（搞这个标准库的人是不是没想过这个返回值多么没用啊？？直接返回一个操作的长度不是更好？），在服务端发回客户端时，这个并不需要被发回来，因为strcat的第1个参数已经能带回操作后的内容了。<BR><BR>3、strncat的第3个参数表示第1个缓冲区参数的长度，如果能把它和第1个参数合起来用一个buffer对象表示，就能省事了。<BR><BR>理想情况下，我们的服务对象这样来写：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">service&nbsp;StringService<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;buffer</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;strcat;<BR>&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;buffer</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;strncat;<BR>};</SPAN></DIV><BR>我们的目的是把老的代码包装成新鲜时髦的服务，当然不用保留老式代码中的指针，以及使用指针和长度2个值来表示一个缓冲区的做法。buffer类在构造时要接受一个size_t参数，指定缓冲区的大小。<BR><BR>这在服务端将产生映射问题，由于这个Method定义的形式和C标准库中的函数形式不一致。<BR><BR>我想应该去实现一个适配器模板类，比如：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">strcat.setFunction&nbsp;(adapter</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">),&nbsp;convert</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;buffer</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt; (::strcat)</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">strncat.setFunction&nbsp;(adapter</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">,&nbsp;size_t),&nbsp;convert</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;buffer</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;length</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">uint</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt; (::strncat)</SPAN><SPAN style="COLOR: #000000">);</SPAN></DIV><BR>convert&lt;void, 0&gt;表示把第0个参数（这里指返回值）转成void类型，length&lt;in&lt;uint&gt;, 1&gt;表示这个参数类型是int&lt;uint&gt;，它是从第1个参数中提取的长度，大致就是使用这种规则，语法可能以后会有变动。<BR><BR>这点内容是我几个月前就在考虑的，也是我想做这个项目的动机，不过直到最近一段时间才从可行性方面仔细考虑。<BR><BR>通过前面几个模板的练习，现在已经大致知道哪些东西是可以用模板做出来，哪些不能使用模板，这应该是最大的收获了。很多东西单靠模板或是虚函数都不好完成，但结合起来就能产生意想不到的效果。<BR><BR>
<HR>
<BR>又仔细想了一下，上面的代码应该还可以修改简化：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">strcat.setFunction&nbsp;(adapter</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">convert</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;buffer</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;( ) (::strcat));<BR><BR></SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">strncat.setFunction&nbsp;(adapter</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">convert</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;buffer</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;length</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">uint</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;( ) (::strncat));</SPAN></DIV><BR>使用一个仿函数来做，函数指针的类型可以从operator ()的参数（模板参数）中推导出来。<img src ="http://www.cppblog.com/cpunion/aggbug/481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-28 22:57 <a href="http://www.cppblog.com/cpunion/archive/2005/09/28/481.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>asgard项目遗留问题　（2005-09-27更新）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/24/416.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 24 Sep 2005 09:00:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/24/416.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/416.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/24/416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/416.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/416.html</trackback:ping><description><![CDATA[asgard项目已经准备了一段时间了，不过有些基本问题还需要考虑，也有一些是新发现的问题，以及自认为比较好的解决办法。<BR><BR>通过第2、第4条的仔细研究，已经渐渐完善、明确了动态部分和静态部分的关系，使得Method包装类所完成的功能渐渐接近于一个函数，而元信息则脱离具体的对象提升到全局（当然还有些小问题没有解决）。<BR><BR><STRONG>1、参数名称的问题。</STRONG><BR><BR>为了与SOAP等基于XML的协议兼容，必须开始就把参数名称考虑在内。<BR><BR>代码经过C＋＋编译器编译以后，类型、变量名称等都不复存在，唯一留下的是RTTI，显然不能解决这个问题。所以只能在定义时把它加入。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">BEGIN_SERVICE(TestService)<BR>&nbsp;&nbsp;&nbsp;&nbsp;METHOD&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">),&nbsp;method1,&nbsp;index,&nbsp;info,&nbsp;result);<BR>END_SERVICE()</SPAN></DIV><BR>如果使用这种方式，index, info, result分别表示变量名字，在宏里面转成字符串，看起来好像不太舒服，而且宏不支持参数个数变化。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">BEGIN_SERVICE(TestService)<BR>&nbsp;&nbsp;&nbsp;&nbsp;METHOD&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">),&nbsp;method1,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">(index,&nbsp;info,&nbsp;result)</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;METHOD&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">),&nbsp;method2,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">result(index,&nbsp;info)</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>END_SERVICE()</SPAN></DIV><BR>这种可能稍稍舒服一点，在Method构造函数或其它地方解析这个字符串，赋给各个参数。不过它的缺点是把编译期应该检查出来的错误，延迟到运行期。如果在编译期来做，又会使接口描述变得很复杂。<BR><BR>只是为了得到参数的名字，就要增加这么些麻烦。<BR><BR>c++0x只是一个库的标准，估计XTI也不会加入这些特性，而且c++0x很遥远，所以暂时以这种方式来做。<BR><BR><STRONG>暂时的解决办法：</STRONG><BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">BEGIN_SERVICE(TestService)<BR>&nbsp;&nbsp;&nbsp;&nbsp;METHOD&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">),&nbsp;method1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;METHOD&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">),&nbsp;method2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;BEGIN_SERVICE_DEFINE(TestService)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;METHOD_DEFINE&nbsp;(method1,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">(index,&nbsp;info,&nbsp;result)</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;test_func);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;METHOD_DEFINE&nbsp;(method2,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">result(index,&nbsp;info)</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">Test::test_method);<BR>&nbsp;&nbsp;&nbsp;&nbsp;END_SERVICE_DEFINE()<BR>END_SERVICE()</SPAN></DIV><BR>缺点是参数名称中的错误，要延迟到运行期才能解决掉。<BR><BR><STRONG>2、服务对象的大小。<BR></STRONG><BR>如果客户端要调用其中一个方法，生成一个TestService，则构造成本太高，特别是一个服务中有多个方法的时候。一个服务容纳了多个方法，而每个方法包含一个vector，以及各个参数，这还没考虑以后的扩展。<BR><BR>所以应该修改调用方式，让它只只需要生成调用所需的最小（少）对象。<BR><BR>这部分考虑还不成熟，暂时可以不管它，而以方法作为考虑的对象。<BR><BR><STRONG>暂时想到的解决办法：</STRONG><BR><BR>Method对象中的parameters容器和各个参数，只在调用operator ()或async_call时，才真正生成出来。<BR><BR>这样的话，Method对象中仅保存一个空的vector。<BR><BR>甚至这个vector也可以只是一个空指针，当调用那几个函数时，才生成一个。<BR><BR>暂时把这个过程命名为Create On Call(COC)。<BR><BR>COC的好处是显而易见的，每个对象将只有8字节，虚表指针＋数据对象的指针，“数据对象”是实际调用时才生成的对象，包括参数vector容器、回调函数指针（可能由动态生成一个委托对象，以适应广泛类型的回调函数）、对象锁（防止干扰到前一个调用）。初始化成本接近0（虚函数表的初始化忽略不计）。<BR><BR>当调用operator()或async_call时（以下简称CALL），将调用create_parameters虚函数，动态生成一个vector。这样，没有调用到的Method不会象原来一样影响到服务对象的构建性能。<BR><BR>这就要求把Method的“元”信息提到全局，当然更符合“元”的本意，原来由服务对象查询Method以获得“元”信息的过程，现在看来也是不合理的。<BR><BR><STRONG>3、in模板可以省略。</STRONG><BR><BR>in是默认的参数类型，返回值则默认为out类型，这都是不需要明确指定的。<BR><BR><STRONG>解决办法：<BR></STRONG><BR>这个问题是比较好解决的，在InOutTypeTraits模板类中，为各个偏特化版本定义一个type类型，InOutTypeTraits＜T＞::type的类型为in＜T＞，InOutTypes＜in＜T＞＞::type的类型为in＜T＞，InOutTypes＜inout＜T＞＞::type的类型为inout＜T＞，InOutTypes＜out＜T＞＞::type的类型为out＜T＞，InList模板类中进行这种转换。<BR><BR><STRONG>4、异步调用队列。</STRONG><BR><BR>在第2点中介绍道：<BR><BR>每个对象将只有8字节，虚表指针＋数据对象的指针，“数据对象”是实际调用时才生成的对象，包括参数vector容器、回调函数指针（可能由动态生成一个委托对象，以适应广泛类型的回调函数）、对象锁（防止干扰到前一个调用）。初始化成本接近0（虚函数表的初始化忽略不计）。<BR><BR>提到了对象锁，这是一种低效的做法，可以使用异步调用队列来替代它。<BR><BR><STRONG>解决办法：</STRONG><BR><BR>当开始一个调用时，临时生成上面所说的“数据对象”，交由一个调用队列去完成。这时，由于Method对象基本不管理数据，所以它成了一个空壳，作用是保存类型信息。<BR><BR>异步调用最好的实现就是整个系统都由异步调用构成，而同步调用是由异步调用模拟而成。原本打算绕过这种方式，用最简单的方法来做，现在好像又绕回来了。<BR><BR>上面这个做法，很好地把元信息和真实数据分开了，所以打算改成这种结构。<BR><BR>5、全局元信息。<BR><BR>通过第4条的研究，已经使得Method对象成为一个空壳，而“数据对象”在没有调用时又不生成，使得自省结构必须重新做。<BR><BR>考察了java等语言的自省，也打算把元信息的位置提升到全局，而每个Method对象将只保留一个全局元信息的指针，这样应该更自然。<BR><BR><BR>（以后遇到的问题只更新到这个文档中）<img src ="http://www.cppblog.com/cpunion/aggbug/416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-24 17:00 <a href="http://www.cppblog.com/cpunion/archive/2005/09/24/416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（四）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/22/383.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Thu, 22 Sep 2005 11:13:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/22/383.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/383.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/22/383.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/383.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/383.html</trackback:ping><description><![CDATA[如《为C＋＋实现一个IDL（三）》一文中所说，还剩最后一个问题，还是使用前面的测试代码说明。<BR><BR>async_call函数的原型是：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;v0,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&nbsp;v1,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;v2,&nbsp;FUNC_TYPE&nbsp;func);</SPAN></DIV><BR>这是模板类根据in/out来产生的。<BR><BR>在异步调用中，参数是和操作保存在一起的，因为要交给线程处理。前面已经说过，Method模板类中将保有这些参数，Method的定义如下（以例子中4个参数的特化版本来说明）：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(A,B,C,D)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;typename&nbsp;Loki::TL::MakeTypelist</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,B,C,D&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a;<BR>&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;b;<BR>&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;c;<BR>&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;d;<BR>&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters.push_back&nbsp;(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">a);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters.push_back&nbsp;(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">b);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters.push_back&nbsp;(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">c);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters.push_back&nbsp;(</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">d);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};</SPAN></DIV><BR>相应地，Base类使用这个特化版本：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TYPES,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;IN_TYPES</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TYPES,&nbsp;IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;IMethod<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;FuncTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TYPES</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;FUNC_TYPE;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};</SPAN></DIV><BR>TYPES模板参数中保存了所有的参数类型，IN_TYPES模板参数中保存了所有的in参数类型，但它们不知道如何来对应起来，async_call也不知道如何把几个参数值交给parameters（在IMethod中定义，见上一篇）。<BR><BR>如果我们在生成IN_TYPES的时候，把它在TYPES中的位置（索引）也一起交给它，就能解决这个问题。<BR><BR>InList第二个模板参数是一个常量，当我们把TYPES交给它时，以上面的代码为例，将会使用T_COUNT值为4的偏特化版本。这时候，将会首先推导出IN_TYPES中的第一个类型int，它在IN_TYPES中的索引是0，并接着调用T_COUNT值是3的偏特化版本，这样递归推导，直到调用T_COUNT值为0的偏特化版本，这个过程就结束了。在这个递归过程中，能够得到各个类型以及对应的“索引”值：int: 4, char: 3, string: 2。<BR><BR>注意这个索引值和实际的索引值是有差别的，实际的索引值应该是4-T_COUNT，所以上面的对应关系应该是：int: 0, char: 1, string: 2。<BR><BR>最初传递给InList的TYPES有4个元素，当它递归调用时，这个值就会依次递减，后面的递归调用并不知道应该用4去减掉T_COUNT作为索引，因为4并没有传递过来。简单的解决办法是再加上一个模板参数，让它往下传递，当然这种方式并不好看，好在我们不是真的必须这么做。<BR><BR>注意，在Base类中，它是知道TYPES的个数的，那么只要用这个数减去前面生成的IN_TYPE的“索引”，就能得到这个类型在TYPES中的真正索引。（这部分真是有点罗嗦）<BR><BR>修改InList模板类，让它生成由<FONT style="BACKGROUND-COLOR: #a9a9a9" color=#a9a9a9> </FONT><FONT style="BACKGROUND-COLOR: #a9a9a9">[ in类型以及in类型在TYPES中的“索引”] </FONT>构成的新Typelist。<BR><BR>首先要增加一个辅助模板类：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;INDEX</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeReversedIndex<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;type;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{value&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;INDEX};<BR>};</SPAN></DIV><BR>它能够保存一个类型，以及一个整数。取名为TypeReversedIndex，意思是说它要保存一个Type和一个ReversedIndex（反的索引）。<BR><BR>InList模板类也要修改，OutList依旧是免费赠送：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;T_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Loki::TL::Length&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::value&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InList<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Head</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isin,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::Typelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeReversedIndex&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Head,&nbsp;T_COUNT</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;typename&nbsp;InList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Tail</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;InList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Tail</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;Loki::TL::MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;T_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Loki::TL::Length&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::value&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;OutList<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Head</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isout,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::Typelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;TypeReversedIndex&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Head,&nbsp;T_COUNT</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;typename&nbsp;OutList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Tail</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;OutList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">typename&nbsp;T::Tail</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;OutList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;Loki::TL::MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};</SPAN></DIV><BR>Base类就可以写出来了：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TYPES,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;IN_TYPES</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TYPES,&nbsp;IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;IMethod<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;FuncTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TYPES</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;FUNC_TYPE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;IN_TYPES&nbsp;type;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{TYPES_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;typename&nbsp;Loki::TL::Length</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TYPES</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::value};<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::type::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::type::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::type::OriginalType&nbsp;v2,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::type</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters[TYPES_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::value])</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">setValue&nbsp;(v0);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::type</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters[TYPES_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::value])</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">setValue&nbsp;(v1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::type</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters[TYPES_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;typename&nbsp;Loki::TL::TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPES,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::value])</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">setValue&nbsp;(v2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};</SPAN></DIV><BR>parameters中存放的是IParameter*类型，这里使用了强制转型，并调用in/inout模板类的setValue方法给它赋值。<BR><BR>为了测试结果，我为IParameter加上了void print () const虚函数，并在in/inout/out模板类中实现它，打印出类型，in/inout类中还将打印出参数值。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;IParameter<BR>{<BR></SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">:<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;print&nbsp;()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>};</SPAN></DIV><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;IParameter<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;value;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;setValue&nbsp;(T&nbsp;v){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;v;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;print&nbsp;()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;typeid(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">).name()&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">:&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;IParameter<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;print&nbsp;()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;typeid(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">).name()&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;inout&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;IParameter<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;value;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;setValue&nbsp;(T&nbsp;v){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;v;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">virtual</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;print&nbsp;()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;typeid(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">).name()&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">:&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};</SPAN></DIV><BR>并在Base::async_call中调用parameters中所有对象的print函数来输出一些调试信息：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;(size_t&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;parameters.size();&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)<BR>&nbsp;&nbsp;&nbsp;&nbsp;parameters[i]</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">print&nbsp;();</SPAN></DIV><BR>简单测试了2种类型，不能保证所有代码都是正确的，毕竟是手工写出来的也没经过检查，模板类在没有实例化的时候某些错误是不会报告的。<BR><BR>测试代码如下：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;test_func&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;v0,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&nbsp;v1,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;v2,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&nbsp;v3)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">===========================================</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test_func(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v0&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v1&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v2&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v3&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;test_func1&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;v0,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&nbsp;v1,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&nbsp;v2,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;v3)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">===========================================</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test_func1(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v0&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v1&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v2&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;v3&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>}<BR><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;m;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">===========================================</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;test_func);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">===========================================</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;m;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">===========================================</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">,&nbsp;test_func1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">===========================================</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;endl;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV><BR>全部代码太长，就不一一罗列于此了，可以点击<STRONG><A href="http://www.cnblogs.com/Files/cpunion/asgard_test.zip">这里</A></STRONG>下载。<BR><img src ="http://www.cppblog.com/cpunion/aggbug/383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-22 19:13 <a href="http://www.cppblog.com/cpunion/archive/2005/09/22/383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（三）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/21/366.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Wed, 21 Sep 2005 12:34:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/21/366.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/366.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/21/366.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/366.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/366.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、修正错误。首先修正第二篇中的一些错误，错误的内容可见第二篇的评论。在Base类中，FUNC_TYPE需要所有的in/out类型，如果Method的模板参数——即函数类型参数——的返回值不是void，则把它装配成out参数，作为FUNC_TYPE函数类型的最后一个参数，这可以通过偏特化来实现。修改Method模板类，把所有类型包装成一个Typelist，直接传递给Base模板类，由Base去推导...&nbsp;&nbsp;<a href='http://www.cppblog.com/cpunion/archive/2005/09/21/366.html'>阅读全文</a><img src ="http://www.cppblog.com/cpunion/aggbug/366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-21 20:34 <a href="http://www.cppblog.com/cpunion/archive/2005/09/21/366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（二）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/20/349.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Tue, 20 Sep 2005 14:34:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/20/349.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/349.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/20/349.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/349.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/349.html</trackback:ping><description><![CDATA[<P>说明：<BR>要看懂后面那部分代码，即使用Typelist的部分，最好预先看过《C＋＋设计新思维》，英文版名为《Modern C++ Design》。<BR>If模板类在写完后想起来好像在哪见过，早晨去公司查阅了一下，在《产生式编程——方法、工具与应用》一书中有讲，英文名为《Generative Programming -- Methods, Tools, and Applications》基本和本篇中一个样。<BR><BR><BR>前2篇乱七八糟地讲了一些，有一个遗留问题，函数原型的推导。<BR><BR>简要描述如下：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;method;<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;同步调用</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;str&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hello</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">&nbsp;value&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">;<BR>method&nbsp;(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;str,&nbsp;value</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;异步调用1</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">method.async_call&nbsp;(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hello</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR><BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;异步调用2</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;test_func&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">);<BR>method.async_call&nbsp;(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">a</SPAN><SPAN style="COLOR: #000000">'</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hello</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;test_func);</SPAN></DIV>
<P><BR>要产生这3种函数形式。参数类型如何转换，是以后的话题，本篇主要解决异步调用的函数原形推导问题。本篇也不讨论Method的模板参数（即那个函数类型）返回类型不为void的情况。<BR><BR>第一种形式，同步调用，比较好处理，参数个数和模板参数的数量相同。<BR><BR>后2种形式，如何让编译器根据in/out来推导出函数原型？<BR><BR>我们需要编译器做这样的处理，async_call的参数类型中，in类型的参数将保留，out类型的参数不需要，inout类型也需要保留。<BR><BR>要用到的Loki头文件：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">static_check.h</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Typelist.h</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR><BR></SPAN><SPAN style="COLOR: #0000ff">using</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">namespace</SPAN><SPAN style="COLOR: #000000">&nbsp;Loki;<BR></SPAN><SPAN style="COLOR: #0000ff">using</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">namespace</SPAN><SPAN style="COLOR: #000000">&nbsp;Loki::TL;</SPAN></DIV>
<P><BR>首先看看in/inout/out的声明。为了简化，这里去掉了跟类型推导无关的部分。</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;NullType&nbsp;();<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;inout<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;T&nbsp;OriginalType;<BR>};<BR></SPAN></DIV><BR>下面Method模板类的声明，使用偏特化来产生代码。为了简化，我只取函数参数个数为4个参数的版本，比照着上面的代码来解释，只解释method.async_call (3, 'a', "hello", test_func);这个版本，因为另一个比它简单。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method<BR>{<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Ret,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Ret(A,B,C,D)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR>{<BR>};</SPAN></DIV>
<P><BR>根据上面Method的定义，Method &lt; void(in<INT>, in<CHAR>, inout<STRING>, out<SHORT>) &gt; ，async_call函数的类型将是：<SPAN style="COLOR: #000000"></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">short</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">,&nbsp;FUNC_TYPE&nbsp;func);</SPAN></DIV></SPAN><BR>实际上FUNC_TYPE应该能够接受更广泛的类型，比如void(int, char, char*, short)，这可以在内部做一些转换，不过本篇的重点不在这里，所以只讲上面的那种形式。<BR><BR>直接在Method类中实现有些麻烦，所以我把这个函数放在一个基类中实现，只要编译器能帮我们推导出下面这种形式就行了：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Ret,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Method&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Ret(A,B,C,D)</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;:&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;B,&nbsp;C&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>};</SPAN></DIV>
<P><BR>注意，这里是以Method &lt; void(in<INT>, in<CHAR>, inout<STRING>, out<SHORT>) &gt;这种形式来讲的，才会有上面那种继承关系。而实际上，由于in/out在参数中的位置、数量都是未知的，要到定义时才能确定，所以使用模板来推导。（入正题了）</P>
<P>也就是说，只要我们能使用静态推导方式，获得A,B,C,D这四个参数中所有的in类型，把它交给Base作为模板参数就成了。</P>
<P>这里需要一个辅助的模板类，用来在编译时帮助推导：<BR><BR></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Loki::CompileTimeError&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;Not_Supported_Type;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">};<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">};<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;inout</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">};<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">enum</SPAN><SPAN style="COLOR: #000000">&nbsp;{isin</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;isout</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">};<BR>};</SPAN></DIV></SPAN><BR>通过另一个模板类InList来帮我们产生所有的in类型，它的结果是一个Typelist。为了方便以后使用，我把out类型产生器也做了一个OutList。<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;CONDITION,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_IF,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_ELSE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;If<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_IF&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_IF,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;_ELSE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;_IF,&nbsp;_ELSE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_ELSE&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;E&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;F&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;G&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;H&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType<BR></SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InList<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isin,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Typelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;typename&nbsp;InList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;InList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G,H</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;InList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isin,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;&gt;</SPAN><SPAN style="COLOR: #000000">::Result<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;B&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;C&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;D&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;E&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;F&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;G&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;H&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;NullType<BR></SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;OutList<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;If&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InOutTypeTraits</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::isout,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;Typelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;A,&nbsp;typename&nbsp;OutList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;OutList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">B,C,D,E,F,G,H</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;OutList&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType,&nbsp;NullType</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;MakeTypelist&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">A</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result&nbsp;Result;<BR>};</SPAN></DIV><BR>它的原理是，根据If模板类来判断一个类型是不是in类型，是的话就把它加入到Typelist中，不是就排除它。<BR><BR>InList <IN<INT>, in<CHAR>, inout<STRING>, out<SHORT>::Result是一个Typelist <IN<INT>, Typelist<IN<CHAR>, Typelist<INOUT<STRING>, NullType&gt; &gt; &gt;类型，说简单点，它和MakeTypelist &lt; in<INT>, in<CHAR>, inout<STIRNG> &gt;::Result是等价的。<BR><BR>现在Base模板类将接受一个模板参数，它是一个Typelist类型，这个不详细讲了，把它的定义写出来：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;T_COUNT&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Length&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IN_TYPE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::value&nbsp;</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;Loki::CompileTimeError&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">false</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;Only_Use_Partial_Specialisation_Version;<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;FUNC_TYPE</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;()<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};<BR><BR>template&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;Base&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">FUNC_TYPE)(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v3,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FUNC_TYPE&nbsp;func)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;async_call&nbsp;(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v0,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v1,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v2,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;TypeAt&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T,&nbsp;</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">::Result::OriginalType&nbsp;v3)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>};</SPAN></DIV><BR>这部分有点多，其实还是比较清晰的。注意这个Base的版本已经不是上面所讲的那个了。<BR><BR>函数原形推导问题就讲完了。上面的代码不一定还能编译，昨天是能编译的，被我修改了一些，为了解释，又改成昨天那样子。<img src ="http://www.cppblog.com/cpunion/aggbug/349.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-20 22:34 <a href="http://www.cppblog.com/cpunion/archive/2005/09/20/349.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（一）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/17/284.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Sat, 17 Sep 2005 11:40:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/17/284.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/284.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/17/284.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/284.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/284.html</trackback:ping><description><![CDATA[<P>前面简单写了点静态结构，这一次将主要关注动态模型以及调用方式。</P>
<P>这个系列的名字叫“为C++实现一个IDL”，实际上应该叫“为C++实现一个Remoting”可能更好一些，说是IDL，主要是想通过宏，使用简单的类型定义达到自动生成调用代码的目的。</P>
<P><STRONG>一、首先来看看调用习惯。</STRONG></P>
<P>从调用习惯入手，主要是因为看到目前有很多库/工具包在调用上都有很多不便之处。假如能在一开始就从这点出发，就能把调用接口设计得更好一些。</P>
<P>先来看看服务端如何开放一个服务。</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 发布为SOAP服务，先生成一个服务容器。<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 服务将发布在localhost的7911上，localhost用来绑定loopback网卡。</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR><BR>    TestService test_service; <BR>    soap_service.addService  (“test_service”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test_service);<BR><BR>    TestService service1;<BR>    soap_service.addService (“HelloService”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">service1);<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">{<BR>        soap_service.run ();<BR>    } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SocketException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>    {<BR>    } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SignalException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>    {<BR>    }<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><BR>我希望就是这么简单，客户端调用有多种方式：<BR>1、 使用服务的IDL定义，直接调用：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">{<BR>        TestService test_service (“test_service”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">soap_service);<BR>        test_service.method1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">);<BR>    } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SocketException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>    {<BR>    }<BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><BR>这种方式比较简单，调用时会检查是否已经连接，然后发送调用请求，并处理调用结果。</P>
<P>2、 服务验证方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR>    TestService test_service;<BR>    soap_service.getService (“test_service”, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test_service);<BR><BR>    </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (test_service)<BR>    {<BR>        </SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">{<BR>            test_service.method1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000">);<BR>        } </SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000"> (SocketException</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> e)<BR>        {<BR>        }<BR>    }<BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><BR>3、 服务发现方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> main ()<BR>{<BR>    SOAPProxy soap_service (</SPAN><SPAN style="COLOR: #000000">7911</SPAN><SPAN style="COLOR: #000000">, “localhost”);<BR>    vector </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> services_name </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> soap_service.getServiceNames ();<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">    IService</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> test_service </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> soap_service.getService (“test_service”);<BR>    </SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000"> (test_service)<BR>    {<BR>        vector </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> methods </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getMethodNames ();<BR>        IMethod</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> method </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getMethod (“method1”);<BR>        vector </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Type</SPAN><SPAN style="COLOR: #000000">*></SPAN><SPAN style="COLOR: #000000"> types </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getParameterType s()<BR>        method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">addArg (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);<BR>        method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">addArg (</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">        method</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">invoke ();<BR>        </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> <IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">    }<BR>    </SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR>}</SPAN></DIV>
<P><STRONG><BR>二、基本需求。<BR><BR></STRONG>简单分析一下，上面一共涉及了哪些类型？<BR>IProxy:<BR>这是所有Proxy类的基类(和接口)，它可以容纳多个服务对象，提供服务绑定、服务查询、服务发现、服务验证。<BR>IService:<BR>所有Service类的基类，可以容纳多个方法(Method)，提供方法查询、服务验证。<BR>IMethod:<BR>所有Method模板类的基类，容纳多个参数，包括返回值，可通过查询参数类型获得方法的类型定义。<BR>IParameter:<BR>所有参数的基类，包含一个参数类型描述和一个参数值。<BR>IType:<BR>所有类型的基类，预定义了一些基本类型，可自定义类型。</P>
<P>看起来挺多的，其实很难接触到这些，只需要使用宏来定义一个服务，就可以通过模板的类型推导，自动生成这些复杂的定义。</P><STRONG>三、调用过程。<BR><BR></STRONG>以下只简单分析一下同步调用，异步调用将是以后的扩充话题。<BR>根据第二节的3种不同调用过程，简要描述如下： 
<OL>
<LI>直接调用。<BR><BR>
<UL>
<LI>生成SOAPProxy，让它连接到远程主机。<BR>
<LI>生成一个TestService对象，设置远程主机上的服务名称，并指定使用SOAPProxy，也即使用SOAP协议。<BR>
<LI>调用TestService::method1方法。根据method1的定义，把服务名称、方法名称、各个in参数等打包成一个“集合”，交给SOAPProxy处理。<BR>
<LI>SOAPProxy把这个“集合”转换成SOAP消息，发送到远程主机，阻塞线程。<BR>
<LI>远程主机上的SOAPProxy对象收到数据，进行解析。当解析出一个服务调用时，把它交给TestService服务处理。<BR>
<LI>TestService解析出一个方法调用，把它交给Method处理。<BR>
<LI>Method解析出各个参数，验证参数类型、完整性等，并执行调用或返回错误。<BR>
<LI>Method调用的返回信息(包括调用结果、返回值、out参数等)被打包成一个“集合”，交给TestService处理。<BR>
<LI>TestService处理后，交给SOAPProxy。<BR>
<LI>SOAPProxy把结果打包成SOAP消息，发回调用端。<BR>
<LI>调用端解析SOAP消息，把OUT参数值赋给调用者提供的对象，调用完成。 </LI></UL>
<P> </P>
<LI>服务验证方式。<BR>
<UL>
<LI>生成SOAPProxy，让它连接到远程主机。<BR>
<LI>生成TestService对象，调用SOAPProxy的getService验证版本。<BR>
<LI>SOAPProxy把TestService对象的信息(名称、成员及基类型等)发送到远程主机，阻塞。<BR>
<LI>远程主机解析收到的信息，查找服务名，并比较查找到的服务类型与解析得到的类型。<BR>
<LI>比较结果发回给调用端。<BR>
<LI>调用端接着采用直接调用的方式，调用远程服务。</LI></UL><BR>这种方式看起来多了一些操作，不过验证的好处是能够减少调用时的异常。 
<P></P>
<LI>服务发现方式。<BR>
<UL>
<LI>生成SOAPProxy，让它连接到远程主机。<BR>
<LI>查询远程开放的服务名称。(可省略)<BR>
<LI>查找特定服务，得到服务描述信息。<BR>
<LI>查找服务中的方法，得到方法描述信息。<BR>
<LI>压入各个参数，并执行调用。<BR>
<LI>调用前先判断参数是否与描述一致，然后调用SOAPProxy生成SOAP消息，发送到远程主机，阻塞。<BR>
<LI>远程主机解析出调用。。。后面过程与第1种方式相同，远程主机并不知道客户端使用的是哪种方式来调用。远程主机处理结束，将返回SOAP消息给调用端。<BR>
<LI>调用端解析出调用结果，并把各个OUT参数的值赋给method对象。</LI></UL><BR>使用这种方式，调用端不需要服务的类型定义。 
<P></P></LI></OL>
<P><STRONG>四、异步调用/异步分派(AMI/AMD)。<BR></STRONG><BR>同步调用时，调用端线程需要等待调用结果，服务端线程也要等待调用结束返回，才处理下一个调用。<BR>为了在服务调用期间让线程能做更多的事：<BR>调用端把调用交给线程池完成，并在调用完成后采用某种机制通知线程处理结果，或者直接由线程池中的调用线程调用结果处理函数。这种方式称为AMI(异步方法调用)。<BR>服务端主线程则把接收到的消息解析后，放入处理队列，由线程池去处理调用过程。当调用完成后，结果放入结果队列，由主线程处理成消息，发送回调用端。这种方式称为AMD(异步方法分派)。<BR>调用端和服务端依旧是使用通讯协议来沟通，双方都不知道对方是否采用了异步方式。</P>
<P>AMI和AMD对于静态定义的服务是有影响的，比如下面一个服务：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService<BR>{<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> method1;<BR>}</SPAN></DIV>
<P><BR>在同步调用时，它的调用方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">TestService test_service;<BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> a;<BR>service.method1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, a); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 或者 service.method1 (3, &a)，打算兼容这2种方式。</SPAN></DIV>
<P><BR>异步调用时，调用方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> method1_result (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">);<BR>TestService test_service;<BR>test_service.method1.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, method1_result); </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 调用完成后，让调用线程去调用method1_result通知调用结果。<BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 或者像下面</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">IMethod</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> result </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service.method1.async_call (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000"> (</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">result</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">done())  </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"> 还有很多好办法，这里只是为了简单。</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">{<BR>    sleep (</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">);<BR>}<BR>cout </SPAN><SPAN style="COLOR: #000000"><<</SPAN><SPAN style="COLOR: #000000"> result</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">getArg(</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">toInt(); <BR></SPAN></DIV>
<P><BR>正如上面演示的一样，异步调用的结果有2种方式去处理。<BR>一是由线程池调用完以后，接着调用一个函数以通知结果。它不需要轮询，不过涉及到了线程问题，增加了一些复杂性。<BR>另一种方式调用结束后，原调用线程在某个适当的“时机”去查询调用结果。这个时机可以是定时查询，也可以是被线程消息通知而去处理。</P>
<P><STRONG>五、其它。<BR></STRONG><BR>这一篇加上前一篇，应该是提到了全部的要点。<BR>目前剩下的唯一一个难点，可能是在处理异步调用时，Method的定义。<BR>正如上面演示的，一个方法在同步调用和异步调用时，就有3种调用方式：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">service.method1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, a);<BR>test_service.method1.async_call(</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, method1_result);<BR>IMethod</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> result </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> test_service.method1.async_call (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">);</SPAN></DIV>
<P><BR>特别地，它如何根据in和个数和out的个数，产生那2个参数个数匹配的异步调用函数？<BR>再来回顾一下method1的定义：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> method1;</SPAN></DIV>
<P><BR>显然有一定的复杂性，不过我认为还是可以处理掉的。拿3个参数的偏特化版本来说明：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Ret, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> A, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> B, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> C</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Ret</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">(A,B,C)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> MethodBase </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">Ret</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">,A,B,C</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR>{<BR>};<BR><BR>template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> Ret</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> A</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> B</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> C</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, </SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> D</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">NullType, IN_COUNT</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">InCount</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000"> A,B,C,D</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">::value </SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> MethodBase<BR>{<BR>};<BR><BR></SPAN></DIV>
<P><BR>通过对MethodBase类的IN＿COUNT参数定义偏特化，即可定义出这些不同的版本。<BR><BR>当然仅仅是知道了IN参数的个数，还没有提取出IN参数的类型，所以还不能生成函数的原型，或许需要把typelist加进来了（loki中的那个）。<BR><BR><BR><BR>这是后面要考虑的内容，今天先想到这。</P><img src ="http://www.cppblog.com/cpunion/aggbug/284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-17 19:40 <a href="http://www.cppblog.com/cpunion/archive/2005/09/17/284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为C＋＋实现一个IDL　（零）</title><link>http://www.cppblog.com/cpunion/archive/2005/09/15/272.html</link><dc:creator>qiezi</dc:creator><author>qiezi</author><pubDate>Wed, 14 Sep 2005 17:27:00 GMT</pubDate><guid>http://www.cppblog.com/cpunion/archive/2005/09/15/272.html</guid><wfw:comment>http://www.cppblog.com/cpunion/comments/272.html</wfw:comment><comments>http://www.cppblog.com/cpunion/archive/2005/09/15/272.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/cpunion/comments/commentRss/272.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cpunion/services/trackbacks/272.html</trackback:ping><description><![CDATA[<P>一、问题。<BR><BR>这段时间考虑实现一个纯C＋＋的分布式服务包装库，简要描述如下：</P>
<P>有如下类和函数：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> Test<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">out</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>};<BR><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">inout</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);</SPAN></DIV></DIV>
<P><BR>想把它们作为服务发布出去，以SOAP或其它方式。发布为一个TestService，并让它携带多一些信息:</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>};</SPAN></DIV></DIV>
<P><BR>C＋＋有许多工具、库来做到这点，但是，都需要生成一堆代码，很是不爽。<BR><BR>其它语言，比如python, java, c#等，都可以通过自省机制，抛开IDL在语言内实现。<BR><BR>C＋＋并非不能做这个，它只是缺少足够的类型信息。比如上面的例子，如果要发布为服务，那么至少应该把它的参数、返回值搞得明确些，否则要么会造成不必要的参数传递，要么会产生错误（把OUT参数取值可不是安全的）。<BR><BR>比如上面出现的int, int&, int*，在作为in参数时，我们是想传递它的值，类型为int。而int*和string*作为out参数时，我们想让它传递指针或引用，当调用返回时，我们给它赋值。<BR><BR>C＋＋语言的类型极为丰富，却没有描述一个参数到底是in还是out。java也没有，但它可以正常序列化一个null值，在C＋＋中，这可能存在一些麻烦。<BR><BR>再考虑一下char*类型，假如它是in参数，那么它是要传递一个字符还是一个字符串？C＋＋语言没有对它进行描述。<BR><BR>所以要实现一个分布式服务包装（或代理）库，必须让发布者提供这些信息。<BR><BR>我们知道，要查询一个远程服务，必须查询相应主机端口，获取服务信息。最简单的服务信息包括：服务列表，每个服务中的方法列表，方法的类型（包括参数和返回值类型，in/out信息等）。<BR><BR>实际上，我们是要为C＋＋增加一些简单的自省能力。上面那个服务发布接口，实际上离这个要求还有很远，再来看一下：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v1, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> v2);<BR>};</SPAN></DIV></DIV>
<P><BR>可以想见，它是没有一点自省能力的，我们如何向它查询，它的名字？它的方法列表？方法的类型？它如何与Test类的成员函数以及test_func函数关联？</P>
<P>二、方向。<BR><BR>要让上面那个服务具有自省能力，要做的扩充其实并不多。考虑下面的代码：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> Service<BR>{<BR>    TestService ();<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func;<BR>};</SPAN></DIV></DIV>
<P><BR>这几个Method可以用自己写的委托类来做。<BR><BR>1、假如我们在TestService的构造函数里给它分配一个“TestService”名字，并且Service类实现了查询名字的接口，那么它就知道它自己的名字了。<BR><BR>2、假如在TestService的构造函数里为各个Method分配名字，并且注册到TestService，那么它就能够查询方法列表。<BR><BR>3、方法的类型？通过模板方式，把各个参数类型收集起来，给个字符串名称就可以了。<BR><BR>使用宏来实现，大概可以写成这样：<BR><BR></P>
<P></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE (TestService)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func, test_func)<BR>END_SERVICE ()</SPAN></DIV></DIV>
<P><BR>通过上面这几个宏，我们能够生成TestService声明。<BR><BR>不过，有几个问题，罗列如下，并一一解决它：<BR><BR>1、如何把函数指针传给它？如何把方法名称传给它？<BR>这个只是C＋＋语言为我们增加了一些麻烦，我们无法在定义成员的地方调用它的构造函数，不过这并不会造成多大障碍。<BR>上面的METHOD宏如果只是生成类的声明，那么函数指针可以省略。我把它加上的原因是，它可以被我用Ctrl+C, Ctrl+V这种世界上最先进的技术原样拷贝下来，并且通过简单修改的方法实现这种世界上最先进的重用。<BR><BR>上面的代码经过修改，结果就成这样：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE (TestService)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>    METHOD (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func, test_func)<BR><BR>    BEGIN_DEFINE (TestService)<BR>        METHOD_DEFINE (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>        METHOD_DEFINE(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>        METHOD_DEFINE(</SPAN><SPAN style="COLOR: #0000ff">int(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func, test_func)<BR>    END_DEFINE ()<BR><BR>END_SERVICE ()</SPAN></DIV></DIV>
<P><BR>看上去对应得非常整齐，修改起来也比较简单。上面那部分被扩充为如下代码：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> Service<BR>{<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func;<BR>    TestService ()<BR>    : Service (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TestService</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR>    {<BR>        test1.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test1</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        test1.setMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test1);<BR>        test2.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test2</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        test2.setMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test2);<BR>        test_func.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test_func</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        test_func.setMethod (test_func);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test3);<BR>    }<BR>};</SPAN></DIV></DIV>
<P><BR>基本上需要的东西都在这里了。<BR><BR>2、客户端的问题。<BR></P>
<P>上面这种映射，直接拿到客户端会有问题，Test类和test_func函数我们并不打算交给客户端，所以使用函数指针会出现链接错误。<BR><BR>实际上客户端不需要这个，我们想办法把它拿掉就行了。客户端实际需要生成的代码如下：<BR><BR></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> TestService : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> Service<BR>{<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2;<BR>    Method </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func;<BR>    TestService ()<BR>    : Service (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">TestService</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">)<BR>    {<BR>        test1.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test1</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test1);<BR>        test2.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test2</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test2);<BR>        test_func.setName (</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">test_func</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>        </SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">-></SPAN><SPAN style="COLOR: #000000">registerMethod (</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">test3);<BR>    }<BR>};</SPAN></DIV></DIV>
<P><BR>还是上面提到的，C++给我们带来的麻烦。这次需要另一组宏来完成它：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE_D (TestService)<BR>    METHOD_D (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1)<BR>    METHOD_D (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2)<BR>    METHOD_D (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func)<BR><BR>    BEGIN_DEFINE_D (TestService)<BR>        METHOD_DEFINE_D (</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test1)<BR>        METHOD_DEFINE_D(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test2)<BR>        METHOD_DEFINE_D(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">), test_func)<BR>    END_DEFINE_D ()<BR><BR>END_SERVICE_D ()</SPAN></DIV></DIV>
<P><BR>METHOD*和METHOD_DEFINE*宏的参数都有一些多余的信息，没有去掉是因为放在一起容易看到写错的地方。（这个技巧来源于前几天看的一篇BLOG，很报歉没有记下地址）<BR><BR>3、使用的问题。<BR><BR>如何才能比较方便地使用？我考虑了下面这种方式：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> T</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> IProxy;<BR><BR>template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> T</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> SOAPProxy;<BR><BR>SOAPProxy </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #000000">TestService</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> service;<BR>service.connect (</SPAN><SPAN style="COLOR: #000000">5000</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">localhost</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> a</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">n </SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">a;<BR>service.test1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, n);<BR>service.test1 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">n);<BR>service.test2 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, n);<BR>service.test2 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">n);<BR>service.test2 (</SPAN><SPAN style="COLOR: #000000">3</SPAN><SPAN style="COLOR: #000000">, NONE);<BR></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN></DIV></DIV>
<P><BR>Method::operator ()的各个参数都将可以接受相容的类型，像上面一样，因为在TestService中我们已经定义了它要传输的值的类型。<BR><BR>a.NONE是什么？其实是为异步调用考虑的。假如指定某个OUT参数为NONE，则这个参数的值并不真正的OUT，而是保存在Method中。实际上Method中保存每个参数的值。<BR><BR>b.Method与Service如何发生关系？<BR>从TestService的定义中我们知道，Method向Service注册自己以实现自省，但它同时也会保存Service的指向。<BR>我们的Proxy实际上是一个继承模板，上面并没有把它指出来。它的定义是：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">template </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> T</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000"> XProxy : </SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000"> T<XPROXY><BR>{<BR>    </SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">};</SPAN></DIV></DIV>
<P><BR>所以我们的TestService其实也是模板类，它将使用XProxy中定义的序列化类。XProxy将实现Service基类中序列化虚函数以及调用虚函数。<BR><BR>当一个Method调用时，它会调用Service的序列化，由于被重写了，所以调用的是XProxy中的序列化方法。这个方法会把这个Method的各in/inout参数序列化，然后执行远程调用，再把调用结果反序列化给inout/out参数。<BR><BR>4、其它想法。<BR><BR>在考虑上面的定义方式时，我也考虑了其它方式，主要是返回值处理的方法，简述如下。<BR><BR>前面我们假设了一段将被开放为远程服务的代码：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> Test<BR>{<BR>    </SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>    </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">out</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>};<BR><BR></SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> test_func (</SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">in</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">inout</SPAN><SPAN style="COLOR: #008000">*/</SPAN><SPAN style="COLOR: #000000"> </SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);</SPAN></DIV></DIV>
<P><BR>在前面的做法中，我们的服务描述是放在那一组宏里面，好处是不用改这段代码，坏处就是代码定义的地方和描述不在一起，协调可能会有一些不便。<BR><BR>我也考虑了另一种做法：<BR><BR></P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000"> Test<BR>{<BR>    idl </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test1 (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>    idl </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, </SPAN><SPAN style="COLOR: #0000ff">out</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000"> test2 (</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);<BR>};<BR><BR>idl </SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">in</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">, inout</SPAN><SPAN style="COLOR: #000000"><</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">></SPAN><SPAN style="COLOR: #000000">) test_func </SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v1, </SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000"> v2);</SPAN></DIV></DIV>
<P><BR>对于实现代码，只需要修改返回值为void的函数，把return;修改为return VOID;，并且为没有写此语句的分支加上此句。<BR><BR>VOID是一个特殊类型的静态变量，专为void返回值的函数设定。<BR><BR>这种做法修改了原有的代码，不过在定义服务时可以节省一些工作：</P>
<DIV style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><SPAN style="COLOR: #000000">BEGIN_SERVICE (TestService)<BR>    METHOD (test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>    METHOD (test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>    METHOD (test_func, test_func)<BR><BR>    BEGIN_DEFINE (TestService)<BR>        METHOD_DEFINE (test1, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test1)<BR>        METHOD_DEFINE (test2, </SPAN><SPAN style="COLOR: #000000">&</SPAN><SPAN style="COLOR: #000000">Test::test2)<BR>        METHOD_DEFINE (test_func, test_func)<BR>    END_DEFINE ()<BR><BR>END_SERVICE ()</SPAN></DIV></DIV>
<P><BR>它所需要的函数类型，将由函数指针推导。<BR><BR>在G＋＋编译器下，可以使用typeof来获得函数指针的类型而不需要真得获得函数指针值，不过目前仅仅在G＋＋下可用。（顺便说一下，typeof已经列入c++0x）<BR><BR>最终我放弃了这个想法，毕竟它要修改现有的代码，某些情况下这是不可能的，而且typeof目前也不能跨编译器。<BR><BR>三、实现。<BR><BR>老实说我现在还没有一份完整的或半完整的实现，大部分想法还在头脑中，测试代码倒是写了不少，主要是用来测试上述想法能否实现，我想大部分情况都已经测试了，只需要有时间来把它实现出来。<BR><BR>这是我近期要做的事之一，争取月内把它做完罢。</P><img src ="http://www.cppblog.com/cpunion/aggbug/272.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cpunion/" target="_blank">qiezi</a> 2005-09-15 01:27 <a href="http://www.cppblog.com/cpunion/archive/2005/09/15/272.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>