CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C++ 语言

[思考]如何给参数确定的函数模板,加上对类型具体要求的显式声明?

楼主ox_thedarkness()2006-03-25 10:33:45 在 C/C++ / C++ 语言 提问

首先考虑下面一个函数模板,他可以打印stl容器到cout。  
   
  template<   class   T   >  
  void   out(   const   T&   coll   ){  
      for(   typename   T::const_iterator   pos   =   coll.begin();   pos   !=   coll.end();   ++pos   )  
          std::cout<<   *pos   <<   '   ';  
  }  
   
  用法:  
  list<int>   coll(   10,   1   );  
  out(   coll   );     //   输出10个1  
   
   
  现在他对T的要求是隐式的。如果   T不包含   T::const_iterator   镶嵌类型,那么实例化该模板就会失败。   但是在函数重载的情况下,隐式声明是不够的。   比如有下面的重载版本   out,他用于输出指针的地址:  
   
  template<   class   T   >  
  void   out(   const   T*   p   ){  
      std::cout<<p;  
  }  
   
  现在假如有   int*   pi,而且只有这个版本的out,那么   out(   pi   )   就会输出pi的地址。   然而一旦两个out版本都出现,两个都可以匹配,而且都不是完美匹配:  
   
  const   T&       -------   int*   ->   const   int*   &  
  const   T*       -------   int*   ->   const   int*  
   
  C++重载规则认为,前者是更好的匹配!所以他会试图实例化那个用于stl容器的版本。那个版本显然不能成功,他要求T::const_iterator,int*当然不支持这个功能。   换句话说,在函数重载的情况下,我们可能需要显式声明   T   的某些特性,比如T拥有一个镶嵌类型   const_iterator。  
   
  ///////////////////////////////////////////////////  
   
  如果是类模板,我们可以这样做:  
   
  template<   class   T,   class   CONSTRANT   =   T::const_iterator   >  
   
  而不提供   CONSTRANT   参数,这样强迫   T   拥有const_iterator   成员。但是函数模板不允许缺省模板参数。  
   
   
  如果函数允许更多参数,我们用缺省参数强迫T类型,可以这样:  
   
  template<   class   T   >  
  void   out(   const   T&   coll,   T::const_iterator*   =   0   ){     //   一个匿名的指针,显式声明T的限制  
      for(   typename   T::const_iterator   pos   =   coll.begin();   pos   !=   coll.end();   ++pos   )  
          std::cout<<   *pos   <<   '   ';  
  }  
   
  上面的例子可以正确强迫T   提供   const_iterator   。   但是在某些环境下,我们没有提供多余参数的权力,比如   operator<<   中。   这种情况如何是好?  
   
  ////////////////////////////////////////////////  
   
  考虑下面的用于容器的版本声明,他的意图是打印容器内容:  
   
  template<   class   Elem,   class   Trait,   class   T   >  
  std::basic_ostream<Elem,   Trait>   operator<<(   std::basic_ostream<Elem,   Trait>&,   const   T&   );  
   
   
  但是,他会令标准库的下面输出指针的版本对   non_const   指针失效:  
   
  template<   class   Elem,   class   Trait,   class   T   >  
  std::basic_ostream<Elem,   Trait>   operator<<(   std::basic_ostream<Elem,   Trait>&,   const   T*   );  
   
   
  现在的问题是:前者既是函数模板(不能提供模板缺省参数),又是运算符   operator<<重载(不能提供额外的函数参数)   如何令前者显式要求   typename   T::const_iterator   必须存在?  
   
  ////////////////////////////////////////////////  
  附测试代码:  
   
  template   <   class   Elem,   class   Trait,   class   T   >  
  std::basic_ostream<Elem,   Trait>&   operator<<(   std::basic_ostream<Elem,   Trait>&   os,     const   T&   coll   ){  
      for(   typename   T::const_iterator   pos   =   coll.begin();   pos   !=   coll.end();   ++pos   )  
          os<<   *pos   <<   '   ';  
      return   os;  
  }  
   
  int   main(){  
      std::list<int>   coll(   10,   1   );  
      std::cout<<   coll   <<std::endl;     //ok  
   
      int*   pi   =   0;  
      //std::cout<<   pi   <<std::endl;         //!!   failed  
  }  
  问题点数:100、回复次数:35Top

1 楼Jinhao(辣子鸡丁·GAME就这样OVER了)回复于 2006-03-25 10:53:44 得分 50

template<typename   _OStream,     typename     T   >  
  void   out(_OStream&   os,     const   T&   coll,   typename   T::const_iterator   *   =   0   ){  
      for(   typename   T::const_iterator   pos   =   coll.begin();   pos   !=   coll.end();   ++pos   )  
          os<<   *pos   <<   '   ';  
  }  
   
  template<typename   _OStream,     typename   T   >  
  void   out(_OStream&   os,     const   T*   p   ){  
      printf("%p",   p);  
  }  
   
  template   <   typename   Elem,   typename   Trait,   typename   T   >  
  std::basic_ostream<Elem,   Trait>&   operator<<(   std::basic_ostream<Elem,   Trait>&   os,     const   T&   coll   )  
  {  
      out(os,   coll);  
      return   os;  
  }  
   
  不过对于提供   template<typename   T>std::ostream&   operator<<(std::ostream&   ,   T);   这样的东西的确很不好...为什么要去打破标准库的规则呢??Top

2 楼xlsue(小林)回复于 2006-03-25 11:39:03 得分 0

很久不用模板了,关注一下。。。Top

3 楼guyanhun(老婆说的都是对的!努力做个好老公!)回复于 2006-03-25 11:50:53 得分 0

study   .  
   
  没看懂啥意思   ~~Top

4 楼corrupt(喜欢 睡在床板下 的思考)回复于 2006-03-25 12:08:04 得分 0

用特例???  
   
  Top

5 楼milee(业余程序员)回复于 2006-03-25 13:35:45 得分 0

好东西  
  日后再学Top

6 楼ox_thedarkness()回复于 2006-03-25 14:02:04 得分 0

哈哈,Jinhao(辣子鸡丁·十八中门口打望)   (   )   思路很有趣,“既然覆盖了标准的版本const   T*   ,那么我就亲自接管被覆盖的部分,实作一份一样的”,但是如你所言,这样仍然破了标准库的规则。    
   
   
  鸡丁的做法想当于一个自定义扩展的库   ——   而且不容于其他库,所以耦合度非常高。  
  当用户需要加入其他匹配度相同或者更低的重载时,不能直接重载operator<<,   而是“注册”有显式要求的out   版本,经由唯一的   const   T&   版本充当中介。    
   
   
  有没有其他技巧,令   operator<<   这样的二元运算符重载能直接加上对模板参数的显式要求?   若是可以直接显式要求,那么就不存在对标准库的规则的破坏了。Top

7 楼ox_thedarkness()回复于 2006-03-25 14:18:36 得分 0

假如   C++   templates   第13章提到的未来方向可能提供的特性已经实现,那么我们可以简单的:  
   
  1   假如下一版C++   标准支持缺省函数模板参数:  
  template   <   class   Elem,   class   Trait,   class   T,   class   M   =   typename   T::const_iterator   >  
       
      利用缺省参数M   强制   T::const_iterator   存在  
   
  2   假如支持typeof   :  
   
  template   <   class   Elem,   class   Trait,   class   T>  
  ...   operator<<(   ...   ,     typeof(T::const_iterator,   const   T&   )   rhs     )  
   
      利用逗号表达式,强制T::const_iterator   存在  
   
   
   
  但是现阶段有什么办法呢?  
  Top

8 楼shenmea00000(学习中~~~)回复于 2006-03-25 15:35:28 得分 0

看不出什么门道~~~~~Top

9 楼Jinhao(辣子鸡丁·GAME就这样OVER了)回复于 2006-03-25 15:38:11 得分 0

重载不允许你去接管...要提供一个泛型的   operator<<(std::ostream&,   const   T&)几乎是不可能,因为现在不能让所有的T都具备operator<<(std::ostream&,   const   T&)对T的concept要求。  
   
  目前的方法只有依赖于提供一层helper这样的东西。而让   operator<<(   std::basic_ostream<Elem,   Trait>&,     const   T&)   进行了泛化[注意不是   operator<<(std::ostream&,   const   T&)],将导致一个很隐蔽的错误。看看上面的第2个out,我用的是   printf("%p",   p);而非   os<<p;   这就是那个错误。即使下一个具有更好的类型系统的C++版本的出现,也未必能解得LZ的问题...   因为LZ的问题相当于用operator   new   去实现   operator   newTop

10 楼howyougen(夫孝,德之本也,教之所由生也)回复于 2006-03-25 21:32:18 得分 0

为什么要对容器操作,而不是对序列操作呢?Top

11 楼ox_thedarkness()回复于 2006-03-25 22:33:50 得分 0

-     -   算了,偶给他加个强一点的制约,要求T是一个双模板参数的模板,暂时堵住   T*   问题。    
   
  而且目前这东西放在偶的一个子名字空间内,暂时不会有冲突。   比起安全,偶还是比较喜欢易用性。  
   
  template   <   class   Elem,   class   Trait,    
                        class   E,   class   Alloc,  
                        template<typename,   typename>   class   T>  
  std::basic_ostream<Elem,   Trait>&   operator<<(  
                        std::basic_ostream<Elem,   Trait>&   os,  
                        const   T<E,   Alloc>&   coll   )  
  {  
      for(   typename   T<E,   Alloc>::const_iterator   pos   =   coll.begin();   pos   !=   coll.end();   ++pos   )  
          os<<   *pos   <<   '   ';  
      return   os;  
  }  
   
   
   
  在偶发现新约束技巧之前,看来这个目前已知唯一完美的做法是你上次那样,对每个容器提供一个单独的模板,不过个人感觉麻烦而且不优雅,要是能给   T   加一些更加实质的显式限制就好了。  
   
   
  恩阿...   暂时放下... 揭帖....Top

12 楼ox_thedarkness()回复于 2006-03-25 22:44:24 得分 0

-     -   算了,明天揭帖...   说不定还有一线希望涅...?  
   
  再次重申问题是:如何给模板参数   T   更加强的限制?   上面的代码中的限制是:   T   是一个双参数模板。   没有办法进一步说明   T有内嵌定义   T::const_iterator   ?Top

13 楼ox_thedarkness()回复于 2006-03-25 22:56:57 得分 0

to   howyougen(谦受益)   (   )    
   
  对序列操作的话有些麻烦,因为你必须同时制定   begin   和   end,   而   cout<<   只接受一个右端参数。   如果用仿函数的话,用起来类似这样:  
   
  cout<<   show_iter(   coll.begin(),   coll.end()   )   <<endl;  
   
  他和  
   
  copy(   coll.begin(),   coll.end(),   ostream_iterator<int>(   cout,   "   "   )   );  
   
  相比短不了多少。而如果像下面那样多方便!  
   
  cout<<   coll   <<endl;  
   
  所以偶目前还没有着手写序列输出。Top

14 楼aflyinghorse()回复于 2006-03-26 00:17:09 得分 0

如何给模板参数   T   更加强的限制?  
  好像目前没有语言层面的支持吧。  
  boost倒是有很多用于概念检查的代码片断,但他的目的是要更早的对模板参数检查,让编译器  
  尽可能早的报告错误。Top

15 楼shantai(阿山)回复于 2006-03-26 06:06:15 得分 0

模板用的不是很多    
   
  关注中Top

16 楼pgmsoul(游侠)回复于 2006-03-26 08:12:00 得分 0

模板函数不支持默认参数,原因何在?Top

17 楼strangerryf(白痴与白痴讨论的结果一定是比白痴更为白痴的结论)回复于 2006-03-26 09:29:20 得分 0

模板不支持默认参数这个是在模板函数才有的限制,在类模板可以支持。  
  小ox真是超级模板粉丝啊,每天晚上都跟那个潜水的同学讨论这个。Top

18 楼xiao2004()回复于 2006-03-26 09:45:09 得分 0

我们并不总是能够写出对所有可能被实例化的类型都是最合适的函数模板   在某些情况    
  下   我们可能想利用类型的某些特性   来编写一些比模板实例化的函数更高效的函数   在有    
  些时候   一般性的模板定义对于某种类型来说并不适用   例如   假设我们有函数模板max()    
  的定义      
  //   通用的模板定义    
  template   <class   T>    
      T   max(   T   t1,   T   t2   )   {    
          return   (t1   >   t2   ?   t1   :   t2);    
  }    
          如果函数模板用const   char*型的模板实参实例化   并且我们还想让每个实参都被解释为    
  C风格的字符串   而不是字符的指针   则通用模板定义给出正确的语义就不正确了   为了获    
  得正确的语义   我们必须为函数模板实例化提供特化的定义      
          在模板显式特化定义   explicit   specialization   definition   中   先是关键字template和一对    
  尖括号   <>   一个小于号和一个大于号   然后是函数模板特化的定义   该定义指出了模板    
  名   被用来特化模板的模板实参   以及函数参数表和函数体   在下面的例子中   为max(const    
  char*,   const   char*)定义了一个显式特化      
  #include   <cstring>    
     
  //   const   char*   显式特化:    
  //   覆盖了来自通用模板定义的实例    
     
  typedef   const   char   *PCC;    
  template<>   PCC   max<   PCC   >(   PCC   s1,   PCC   s2   )   {  
      return   (   strcmp(   s1,   s2   )   >   0   ?   s1   :   s2   );    
  }    
          由于有了这个显式特化   当在程序中调用函数max(const   char*,const   char*)时   模板不会    
  用类型const   char*来实例化   对所有用两个const   char*型实参进行调用的max()   都会调用这    
  个特化的定义   而对于其他的调用   根据通用模板定义实例化一个实例   然后再调用它    
   
   
  不晓得楼主是不是要的这些类似的东东?  
  c++   primer书上Top

19 楼Acoolice()回复于 2006-03-26 10:30:05 得分 0

学习Top

20 楼ox_thedarkness()回复于 2006-03-26 11:02:39 得分 0

谢谢楼上的,不过可惜不是的。   现在的问题不是重载或者特化不够细致,而是两个不同的重载冲突,引发二义性或者一个覆盖了另一个。  
   
  今天遇到更加麻烦的问题...   模版重载真叫人头大...   下面这数组版本的   <<   为什么在VC下能用,在gcc下不能用啊?  
   
  包含下面代码,VC下假如有数组   int   str[any],     用   cout<<   str   即可输出其内容;而gcc下第一个模板函数则被默认的比下来了?只是和定义之前一样输出首地址而已。  
   
  //   operator<<   on   arrays    
  //   There   is   a   pitfall   in   this   implementation  
  //   It   conflicts   with   standard   lib   on   const   char*   version  
  //   WARNING:     this   function   would   cover   the   default   const   char*   version  
  //   that   would   cause   preformance   decline  
  template   <   class   T,   size_t   sz   >  
      std::ostream&   operator<<(   std::ostream&   os,     const   T(&ar)[sz]   ){  
      for(   size_t   i   =   0;   i   <   sz;   ++   i   )   os<<   ar[i]   <<   '   ';  
      return   os;  
  }  
   
  //   This   template   avoid   ambiguous   on   const   char*   in   the   occasion   of   ostream   output  
  //   It's   a   full   matching   overload.     This   is   to   cover   the   pitfall   of   the   array   out.  
  std::ostream&   operator<<(   std::ostream&   os,     const   char*   ar   ){  
      if(   !ar   )   return   os<<   (void*)   ar;  
      while(   *ar   )   os<<*ar++;  
      return   os;  
  }  
   
  Top

21 楼aflyinghorse()回复于 2006-03-26 14:50:21 得分 0

我再   vc7   和   dev-cpp下的结果是一样的   :   1   2   3  
   
  下面是这个程序:  
   
  #include   <iostream>  
  using   namespace   std;  
   
  //   operator<<   on   arrays    
  //   There   is   a   pitfall   in   this   implementation  
  //   It   conflicts   with   standard   lib   on   const   char*   version  
  //   WARNING:     this   function   would   cover   the   default   const   char*   version  
  //   that   would   cause   preformance   decline  
  template   <   class   T,   size_t   sz   >  
      std::ostream&   operator<<(   std::ostream&   os,     const   T(&ar)[sz]   ){  
      for(   size_t   i   =   0;   i   <   sz;   ++   i   )   os<<   ar[i]   <<   '   ';  
      return   os;  
  }  
   
  //   This   template   avoid   ambiguous   on   const   char*   in   the   occasion   of   ostream   output  
  //   It's   a   full   matching   overload.     This   is   to   cover   the   pitfall   of   the   array   out.  
  std::ostream&   operator<<(   std::ostream&   os,     const   char*   ar   ){  
      if(   !ar   )   return   os<<   (void*)   ar;  
      while(   *ar   )   os<<*ar++;  
      return   os;  
  }  
   
   
  int   main()  
  {  
          int   a[3]={1,2,3};  
           
          cout   <<   a;  
           
          cin.get();  
  }  
  Top

22 楼aflyinghorse()回复于 2006-03-26 14:51:53 得分 0

LZ试试新版本的   dev-cpp?Top

23 楼pongba(刘未鹏|http://blog.csdn.net/pongba)回复于 2006-03-26 23:46:31 得分 50

to   ox_thedarkness():  
  很简单,既然不能在参数上和模板缺省参数上做文章,那么在返回类型上用enable_if不就行了?  
  例如:  
   
  template<typename   T>  
  typename   boost::enable_if<has_const_iterator<T>   >::type  
  f(...){...}  
   
  另外,const   T&跟const   T*的重载决议并不像你想的那样是前者优于后者,实际上,不管p是int*还是int   const*,当前标准下的结果都应该是后者优于前者。对于int*,是exact   match跟qualification   conversion的比较,高下立判。然后对于int   const*,重载决议不能决出结果,partial   order   rules这时就会接管任务,根据目前的rule,仍然是后者更特殊化一些。不过由于这一部分的规则十分晦涩,鲜有编译器能够完全conformance的实现,所以才会一个编译器一个样。目前partial   order的规则还在修订中,所以建议还是不要依赖这一黑暗角落。  
   
  --  
  C++的罗浮宫  
  http://blog.csdn.net/pongbaTop

24 楼ox_thedarkness()回复于 2006-03-27 11:06:19 得分 0

-     -b   昨天一整天rp了,看不见帖子正文,现在好了...  
   
  to   aflyinghorse()   (   )     的确是版本,偶原来   devcpp   4.9.8.0   ;装了   devcpp   4.9.9.2   之后成功了。  
   
  boost::enable_if   ?   谢pongba(刘未鹏)   ,没怎么用过boost,偶下午仔细研究下...   boost还真强啊。  
   
  现在这里的规则真是黑暗...   昨天又遇到一个重载决议VC7   与   devcpp   不同的情况。   感觉目前   C++   模版的确强大,但是表达能力并不够强,规则也并不完善,尤其是决议部分相当复杂和诡异。Top

25 楼ox_thedarkness()回复于 2006-03-27 12:26:17 得分 0

-     -   厄,boost::has_const_iterator   在哪个头文件里面?  
   
  boost\type_traits.hpp   里面似乎没有的说Top

26 楼pongba(刘未鹏|http://blog.csdn.net/pongba)回复于 2006-03-27 13:43:01 得分 0

has_const_iterator不是boost里的,你不会自己写么?呵呵。Top

27 楼aflyinghorse()回复于 2006-03-27 15:51:51 得分 0

has_const_iterator   怎么写?  
  利用模办类的特化?Top

28 楼sandrowjw(我的小猫照片给弄坏了,心都碎了)回复于 2006-03-27 16:38:45 得分 0

mark  
   
  以前见过boost里判断两个类是否继承关系的trait,感觉判断const_iterator应该比那个简单,总之就是类似那个返回类型长度不同的函数重载(Loki里好像也有)。Top

29 楼ox_thedarkness()回复于 2006-03-27 16:46:54 得分 0

=     =   确实不会...   瞎写了一下还是不行,下面的写法在   VC7.1   和   DevCPP   4.9.9.2   都通不过过:  
   
  template   <typename   T>  
  struct   has_iter{  
          typedef   void   void_type;  
          typedef   T   type;  
          typedef   typename   T::const_iterator   type_must_exsit;  
  };  
   
  template   <typename   T>  
  typename   has_iter<T>::void_type   f(   const   T&   coll   ){  
          copy(   coll.begin(),   coll.end(),   ostream_iterator<   T::value_type   >(   out,   "   "   )   );  
          cout<<endl;  
  }  
   
  template   <typename   T>  
  void   f(   const   T*   n   ){  
          cout<<   n   <<endl;  
  }  
   
   
  int   main(){  
          list<int>   coll(10,   1);  
   
          int*   i   =   0;  
          f(   coll   );  
          f(   i   );  
  }Top

30 楼pongba(刘未鹏|http://blog.csdn.net/pongba)回复于 2006-03-27 18:31:06 得分 0

http://blog.csdn.net/pongba/archive/2004/08/24/82783.aspxTop

31 楼Jinhao(辣子鸡丁·GAME就这样OVER了)回复于 2006-03-27 23:06:51 得分 0

template<typename   _T>  
  class   has_const_iterator  
  {  
          template<typename   _U>  
          static   int   _m_dispatcher(   typename   _U::const_iterator   *   );  
   
          template<typename   _U>  
          static   char   _m_dispatcher(...);  
  public:  
          static   const   bool   value   =   sizeof(_m_dispatcher<_T>(0))   -   sizeof(char);  
  };Top

32 楼aflyinghorse()回复于 2006-03-27 23:29:57 得分 0

简单测试一下楼上的程序:  
   
  #include   <iostream>  
  #include   <vector>  
  using   namespace   std;  
   
  template<typename   _T>  
  class   has_const_iterator  
  {  
          template<typename   _U>  
          static   int   _m_dispatcher(   typename   _U::const_iterator   *   );  
   
          template<typename   _U>  
          static   char   _m_dispatcher(...);  
  public:  
          static   const   bool   value   =   sizeof(_m_dispatcher<_T>(0))   -   sizeof(char);  
  };  
   
  int   main()  
  {  
  cout   <<   "int   has_const_iterator:   "   <<   has_const_iterator<int>::value   <<   endl;  
  cout   <<   "vector   has_const_iterator:   "   <<   has_const_iterator<vector<int>   >::value   <<   endl;  
   
          cin.get();  
  }  
   
  结果是:  
  int   has_const_iterator:   0  
  vector   has_const_iterator:   1  
   
  Top

33 楼ox_thedarkness()回复于 2006-03-28 00:29:34 得分 0

喔阿...   真神阿...   谢Jinhao(辣子鸡丁·十八中门口打望)   (   )   的,   ok   了~~  
   
   
  pongba(刘未鹏)   (   )   的文章研究了半天...   刚才看了鸡丁的才发现原来偶   ==   和   !=   用反了...   orz...   怪不得不行,那壶不开提哪壶....   真失败阿...   而且诡异的是,一个方法OK其他方法也莫名其妙OK...     -     -b      
   
   
  然后发现VC   成功了但是   DevCPP   失败了...   修改中发现VC下又不行了...   苦海研究中...   不过应该差不多了。  
   
   
   
  恩~~   那么...   最后一个问题...   能否令   basic_stream   对应的   operator<<   重载同类参数呢?  
  比如,   书写两个对应(或者间接对应)   const   T&   的重载版本,   但是第一个要求   has_const_iterator<T>   ,第二个则要求   is_a_pair<T>  
   
  即,令自定义的   operator<<   重载只要特性声明不通过,不会阻止其他相似重载?Top

34 楼ox_thedarkness()回复于 2006-03-28 01:33:27 得分 0

恩搞定了~~   现在偶的数组输出模板不会覆盖标准的   char*   版,   stl   模板也更加准确了~~  
   
  赞~~   只剩下如何不影响其他重载的问题   ——   返回值不属于重载要求部分;   如何令   “实际参数对应版本相同”   的模板不相互冲突呢?Top

35 楼ox_thedarkness()回复于 2006-03-28 01:56:05 得分 0

哦~~   测试了一下发现居然可以重载?   看来以前对模版重载的看法是错误的呢~~  
   
  好~~   揭帖~~Top

相关问题

  • 模板函数的参数问题
  • 求助:含有函数指针参数的函数模板
  • 函数模板问题(带一个函数指针参数)
  • 模板函数的模板参数能否用缺省值~~???
  • template并不实例化模板函数中的参数?
  • 模板类不可以作为函数参数吗?
  • 用模板类作函数参数发生的问题
  • 模板函数
  • 函数模板
  • 模板参数T2如何缺省为 和模板参数T1相关 的函数指针类型?

关键词

  • .net
  • c++
  • 模板
  • 函数
  • template
  • boost
  • 决议
  • 指针
  • 版本
  • 特化

得分解答快速导航

  • 帖主:ox_thedarkness
  • Jinhao
  • pongba

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo