cyt
发现自己是越来越懒了,竟然原来有大半年没有写blog。

今天是中秋节,先祝各位看官中秋节快乐、人月两团圆!!!!

这大半年什么都干了半桶水:javascript、HTML、servlet、JSP、php、python、COM……虽说干得不精,但也有一点点收获……

C++论坛当然还是讨论回C++。
首先推荐一本书:
《Exceptional C++ Style》Herb Sutter著
Her Sutter的多篇著作都被视为C++开发的经典教本。这本书跟《Exceptional C++》的不同在于更多地讨论style。作者根据自己的经验,对C++的编写提出了很多准则。作者对这些准则的来龙去脉说得清清楚楚,为什么要这样做,不做会有什么后果,在什么编译器下面准则有什么不同的表现等等……比某人出版的C++规范,提出一堆无关痛痒不知所云的规则来的实在得多。
看完以后回顾一下自己之前的代码,简直汗颜,重新燃起重写的冲动……
再说一件小事,就在看完这本书的若干天后,忽然发生一件奇事。某个程序一直编译运行都好好的。这天换了编译环境,程序运行不断core dump,gdb跟了一下是说某个exception没有catch,但是代码里面明明写了catch的,为什么抓不住呢。幸好看了这本书(不是卖广告,汗),第13条……中间有某个函数的异常声明不正确。简单说就是函数1声明会抛出异常A和B,但函数1里面调用了函数2,函数2会抛出异常C。于是,在调用函数1的时候尽管声明了cacth异常C也无济于事,C就是不能处理。(这个不是所有编译器的标准行为)

另外收集了几个C++ lib
QuickFunctor 看名字就知道是Functor的lib。用来做functor,signal/slot当然不在话下。有趣之处在于它实现了一些boost::bind的功能(不依赖boost,但可以和boost、loki、TR1等一起使用)。给些例子会清晰一点:

struct Car
{
    
string make;
    
string model;
    
int mpg;

    Car(
const string& make, const string& model, int mpg) : make(make), model(model), mpg(mpg) {}
};

void findCars(vector<Car>& v, const Functor<bool (Car&)>& test)
{
    vector
<Car>::iterator it;
    it 
= partition(v.begin(), v.end(), test);

    cout 
<< "found " << it - v.begin() << " result(s):\n------------------\n";
    
for (vector<Car>::iterator it1 = v.begin(); it1 != it; ++it1)
    {
        cout 
<< (*it1) << endl;
    }
    cout 
<< "**************************************\n";
}

bool hasTdi(const string& s)
{
    
return string::npos != s.find_first_of("TDI");
}

    cout 
<< "Cars that have at least 23 mpg\n";
    findCars(v, mkF(
&Car::mpg) >= 23);

    cout 
<< "Cars that have the mpg between 23 and 41\n";
    findCars(v, mkF(
&Car::mpg) >= 23 && mkF(&Car::mpg) <= 41);

    cout 
<< "Toyotas that have at least 25 mpg\n";
    findCars(v, mkF(
&Car::make) == "Toyota" && mkF(&Car::mpg) >= 25);

    vector
<Car>::iterator it;
    it 
= find_if(v.begin(), v.end(), mkF(hasTdi).comp<1>(mkF(&Car::model)));
    
//  mkF(hasTdi).o(mkF(&Car::model)) is a shortcut for the test above
    cout << "A car that has TDI: " << (*it) << endl;

个人觉得比boost的简洁一些。不过boost的bind加上的lambda实在是无敌。


另外收藏一个lib是rapidxml 其特点就是完全是C++ header,lib本身不需要编译,除了STL不需要其他的lib,STL风格的接口。还有一个是我最想要的,对XML内容的访问可以通过引用方式,不需要额外分配内存。举例说,假如有一个char * p指针,并分配了一大片内存空间,在里面保存了XML的完整内容。经过parse后,我想获得其中一个node的内容,那我可以选择一种方式,直接引用p所指向的内存中的一部分来获得node的内容,而不需要重新分配一段空间来保存。
以往我一直选用CMarkup作为C++的parser,目的就是图他简单。现在发现rapidxml后,发现rapidxml似乎比CMarkup简单易用,更重要的是rapidxml完全开源,不像CMarkup那样还要分不同的license。对于简单的访问XML,觉得这个rapidxml足够了。

asio 说到网络的异步响应框架,首先想到的就是ACE的proactor。但是个人一直觉得ACE是在有愧于C++,C语言的痕迹太深了,估计是“出道”太早的缘故。boost类库迟迟没有thread、socket方面的lib放出。asio似乎可以填补了这两个空白。asio基于boost,类库的风格以及提供的接口也跟boost十分相似。还是给段例子实际:
#include <ctime>
#include 
<iostream>
#include 
<string>
#include 
<boost/bind.hpp>
#include 
<boost/shared_ptr.hpp>
#include 
<boost/enable_shared_from_this.hpp>
#include 
<asio.hpp>

using asio::ip::tcp;

std::
string make_daytime_string()
{
  
using namespace std; // For time_t, time and ctime;
  time_t now = time(0);
  
return ctime(&now);
}

class tcp_connection
  : 
public boost::enable_shared_from_this<tcp_connection>
{
public:
  typedef boost::shared_ptr
<tcp_connection> pointer;

  
static pointer create(asio::io_service& io_service)
  {
    
return pointer(new tcp_connection(io_service));
  }

  tcp::socket
& socket()
  {
    
return socket_;
  }

  
void start()
  {
    message_ 
= make_daytime_string();

    asio::async_write(socket_, asio::buffer(message_),
        boost::bind(
&tcp_connection::handle_write, shared_from_this(),
          asio::placeholders::error,
          asio::placeholders::bytes_transferred));
  }

private:
  tcp_connection(asio::io_service
& io_service)
    : socket_(io_service)
  {
  }

  
void handle_write(const asio::error& /*error*/,
      size_t 
/*bytes_transferred*/)
  {
  }

  tcp::socket socket_;
  std::
string message_;
};

class tcp_server
{
public:
  tcp_server(asio::io_service
& io_service)
    : acceptor_(io_service, tcp::endpoint(tcp::v4(), 
13))
  {
    start_accept();
  }

private:
  
void start_accept()
  {
    tcp_connection::pointer new_connection 
=
      tcp_connection::create(acceptor_.io_service());

    acceptor_.async_accept(new_connection
->socket(),
        boost::bind(
&tcp_server::handle_accept, this, new_connection,
          asio::placeholders::error));
  }

  
void handle_accept(tcp_connection::pointer new_connection,
      
const asio::error& error)
  {
    
if (!error)
    {
      new_connection
->start();
      start_accept();
    }
  }

  tcp::acceptor acceptor_;
};

int main()
{
  
try
  {
    asio::io_service io_service;
    tcp_server server(io_service);
    io_service.run();
  }
  
catch (std::exception& e)
  {
    std::cerr 
<< e.what() << std::endl;
  }

  
return 0;
}

暂时不清楚asio的性能如何。ACE经过千锤百炼,无数的应用实践,其地位不是这么容易动摇。但asio的封装方式是否值得ACE效仿呢。
posted on 2007-09-25 12:16 cyt 阅读(2079) 评论(4)  编辑 收藏 引用
Comments
  • # re: 中秋节快乐
    梦在天涯
    Posted @ 2007-09-25 15:13
    LZ是用c++做网络的吗,以后多向你学习~!  回复  更多评论   
  • # re: 中秋节快乐
    zcpro
    Posted @ 2007-09-26 17:38
    asio已经被并到boost里了,还在修改,没有完成  回复  更多评论   
  • # re: 中秋节快乐
    小猪
    Posted @ 2007-09-29 14:59
    弱弱的问一句: rapidxml 修改了节点之后,怎么保存数据?
      回复  更多评论   
  • # re: 中秋节快乐
    cyt
    Posted @ 2007-10-27 09:49
    to zcpro:我也看到了asio说加入boost,不过boost的标准包里面还没有看到它的踪影。当年spirit也有这样的现象。估计加入boost大家庭“手续”还是挺麻烦的。

    to 小猪:我暂时还没有用到保存,我也只是暂时用到读取部分。迟点用到的时候我再回复你吧。
      回复  更多评论   

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理