|
2011年7月11日
在我的上一篇隨筆里的模板代碼在vs2010下可以編譯通過,在gcc 4.4.3下卻報錯,后來請教師兄說可能是gcc版本太低,對模板的要求更苛刻,他用的gcc 4.5編譯可以通過,所以一時心血來潮編譯安裝個gcc 最新版,也就是gcc 4.6.1 我參照了這篇博客 http://www.iteye.com/topic/1111655 ,但是安裝過程中遇到了些問題,這里記載下,希望給遇到相同問題的一個參考. 在gcc-4.6.1下configure時出來 check CLooG installed....no(差不多是這意思,具體錯誤信息忘了),我在Synaptic Package Manager里搜索cloog,將libcloog-ppl-dev和libcloog-pll0安裝了,configure通過:-) make && make install 都順利通過:-) 我編譯我們的開源項目stupidalgorithm http://code.google.com/p/stupidalgorithm/ ,編譯通過,但運行不通,提示需要庫GLIBCXX_3.4.15,這時將 gcc-4.6.1/i686-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.16復制到/usr/lib,然后ln -s libstdc++.so.6 libstdc++.so.6.0.16,然后sudo ldconfig即可:-)
2011年7月9日
下面是示例代碼,在vs2010下編譯成功,但在linux下編譯報錯。 基類com_alg代碼片段: 1 template <typename real_para> 2 class com_alg 3 { 4 public: 5 com_alg(std::string conf_path) 6 { 7 // 8 } 9 virtual ~com_alg() { } 10 }; 子類de_alg代碼片段: 1 #include "com_alg.h" 2 3 class de_alg 4 :public com_alg<de_para> 5 { 6 public: 7 de_alg(std::string conf_path): 8 com_alg(conf_path) 9 { 10 } 11 ~de_alg() { } 12 }; 注意de_alg代碼第8行紅色部分,在vs2010下編譯通過,但是在linux(g++ 4.4.3)下編譯出錯: de_alg.h: In constructor ‘de_alg::de_alg(std::string)’: de_alg.h:30: error: class ‘de_alg’ does not have any field named ‘com_alg’ de_alg.h:30: error: no matching function for call to ‘com_alg<de_para>::com_alg()’ com_alg.h:29: note: candidates are: com_alg<real_para>::com_alg(std::string) [with real_para = de_para] com_alg.h:27: note: com_alg<de_para>::com_alg(const com_alg<de_para>&) 將代碼改為 com_alg<de_para>(conf_path)編譯通過,大家能幫忙解釋下不?
2011年3月22日
這段時間要寫服務器負載均衡算法和調度策略,但我沒有接觸過這方面的知識,網上有很多方法,如 輪循法,加權輪循法,最小連接數調度等方法,我想用加權輪循,但對權植和如何分配服務器不太清楚,有誰了解的請教下,不勝感激....
2011年3月21日
前幾天安裝了win7,挺好用的,比xp用起來還是舒服多了,裝完后ubuntu系統進不了了,幾經折騰終于搞定,記載下...同時也告誡自己,系統遇到問題了要有耐心,慢慢總會找到解決方法的,怎么也比重裝來的快,廢話少說啦...
1. 用ubuntu live CD啟動,打開終端.
2. 網上說的方法大致是:
sudo grub grub>find /boot/stage1 ---->輸出(hdx,y) grub>root (hdx,y) grub>setup (hd0) grub>quit
但是我按照上面的方法 不是說file not found就是no device.然后運行了sudo grub-install --root-directory=/mnt /dev/sda 命令,再次執行上面步驟,成功.reboot
如果重啟后系統出現grub,那么你是幸運的,我沒那么幸運,系統進入grub命令模式, :-( grub>
這時候就要用到grub命令了,其實這時即可以進win7也可以進ubuntu,進ubuntu修復grub吧,命令如下
grub> find /boot/grub/core.img ----> (hdx,y) grub> root (hdx,y) grub> kernel /boot/grub/core.img grub> boot
這下就會啟動linux,進入終端,輸入sudo grub-install /dev/sda,OK
如果要進入win7,輸入如下命令即可: grub> rootnoverify (hd0,0) grub> chainloader +1 grub> boot
:-)
2011年1月16日
pimp idiom的詳細說明可以訪 http://www.gotw.ca/gotw/024.htm(這個網站好像被墻了,很諷刺),其實就是將定義與實現分開。 在我博客上一篇隨筆《關于高內聚低偶合》提到的問題,pimp idiom對降低程序偶合有一定的幫助,下面是我的理解思路,大家有好的意見或者更好的方法可以一起討論下: 1 class Para_Base 2 { 3 // 4 }; 5 6 class GA_Para 7 :public Para_Base 8 { 9 // 10 }; 11 12 class Alg_Base 13 { 14 public: 15 Alg_Base(Para_Base *p) 16 :m_pPara(p) { } 17 // 18 protected: 19 Para_Base *m_pPara; 20 }; 21 22 class GA_Alg 23 :public Alg_Base 24 { 25 // 26 public: 27 GA_Alg(GA_Para *pGA) 28 :Alg_Base(pGA) { } 29 }; 參數基類Para_Base和特定的算法參數類GA_Para都沒有改變。 算法基類Alg_Base的模板去掉了,同時添加了一個指向參數基類Para_Base的指針成員變量,而以前用的是模板指針。并且修改了構造函數,構造函數接受一個指向Para_Base的指針并賦給m_pPara。 特定算法類GA_Alg繼承自算法基類Alg_Base,但修改了構造函數,接受指向GA_Para的一個指針,然后調用父類Alg_Base的構造函數,這樣的結果便是m_pPara指向的是GA_Para實例,等價于Para_Base *m_pPara = new GA_Para(); 相對于上一篇提到的模板實現,pimp idiom的偶合更低些,而且pimp idiom應用也非常廣泛。
2011年1月13日
最近遇到的一個問題,大伙來討論一下,希望得到高手的指點,代碼的結構是這樣的: 1 class Para_Base 2 { 3 4 }; 5 6 class GA_Para 7 :public Para_Base 8 { 9 10 }; 11 12 template <typename Para_Type> 13 class Alg_Base 14 { 15 // 16 shared_ptr<Para_Type> m_pPara; 17 }; 18 19 class GA_Alg 20 :public Alg_Base<GA_Para> 21 { 22 23 } 解釋一下,一個參數基類,是各種算法參數的公共基類,第二個類是GA算法的參數類,繼承自Para_Base,第三個類是各種算法的基類,是個模板類,模板參數類型是算法參數類型,如GA_Para,第4個類是GA算法類,繼承自Alg_Base ,這樣m_pPara對不同的算法指向不同的參數,但這樣改動一下代碼,程序得從頭重新編譯,因為程序庫的確比較大,編譯起來挺花時間的,(這是師兄帶我寫的一個智能演化算法的庫,即將完成,我們打算開源,完成后再通告大家)大家有沒有更好的設計方法,比如把定義與實現分開,還望大家多發表些意見,不勝感激。
下面介紹如何從配置文件中讀參數,配置文件中采用name = value的形式,#行表示注釋. 1 #include <boost/program_options.hpp> 2 3 #include <vector> 4 #include <iostream> 5 #include <string> 6 #include <algorithm> 7 #include <iterator> 8 #include <fstream> 9 using std::copy; 10 using std::vector; 11 using std::string; 12 using std::cout; 13 using std::cerr; 14 using std::endl; 15 using std::exception; 16 using std::ostream; 17 using std::ifstream; 18 using std::ostream_iterator; 19 20 namespace po=boost::program_options; 21 22 // output vector. 23 template <typename T> 24 ostream& operator<<(ostream& os, const vector<T>& v) 25 { 26 copy(v.begin(), v.end(), ostream_iterator<T>(os, " ")); 27 return os; 28 } 29 30 int main(int argc, char*argv[]) 31 { 32 try 33 { 34 string conf_file; 35 po::options_description desc("general descriptions."); 36 desc.add_options() 37 ("help", "generate help information") 38 ("config,c", po::value<string>(&conf_file)->default_value("compiler.conf"), "compiler configure file") 39 ("input-file", po::value<vector<string> >(), "input files") 40 ("link-file,l", po::value<vector<string> >()->composing(), "link file"); 41 42 po::positional_options_description p; 43 p.add("input-file", -1); 44 45 po::variables_map vm; 46 //po::store(po::parse_command_line(argc, argv, desc), vm); 47 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); 48 po::notify(vm); 49 50 51 if(vm.count("help")) 52 { 53 cout<<desc<<endl; 54 return 1; 55 } 56 57 // add following lines 58 ifstream i_conf(conf_file.c_str()); 59 if(!i_conf) 60 { 61 cerr<<"Configure file not exit.\n"; 62 return -1; 63 } 64 else 65 { 66 po::store(po::parse_config_file(i_conf, desc), vm); 67 notify(vm); 68 } 69 70 if(vm.count("input-file")) 71 { 72 cout<<"Input files: "<<vm["input-file"].as<vector<string> >() 73 <<"\n"; 74 } 75 76 if(vm.count("link-file")) 77 { 78 cout<<"Link file: "<<vm["link-file"].as<vector<string> >() 79 <<"\n"; 80 } 81 } 82 catch(exception& e) 83 { 84 cout<<e.what()<<endl; 85 return -1; 86 } 87 88 return 0; 89 } 90 第38行添加了config參數命令,接受一個string類型值,并將默認值設為compiler.conf. 第40行添加了composing()方法,這表示程序將從不同的數據源中獲得數據并組合起來. 第66行解析配置文件并存儲至vm. 接下來代碼便是比對vm中選項值,簡單吧:) boost文檔里介紹了隱藏選項和存放多姐選項的方法, http://www.boost.org/doc/libs/1_45_0/doc/html/program_options/tutorial.html#id2073299
boost program_options庫可以幫助我們解析程序參數,支持命令行形式和配置文件形式,獲得(name, value)對.下面我們以一個模擬編譯器例子介紹program_options庫的應用,在下一節繼續介紹program_options整個庫. 1 #include <boost/program_options.hpp> 2 3 #include <vector> 4 #include <iostream> 5 #include <string> 6 #include <algorithm> 7 #include <iterator> 8 using std::copy; 9 using std::vector; 10 using std::string; 11 using std::cout; 12 using std::endl; 13 using std::exception; 14 using std::ostream; 15 using std::ostream_iterator; 16 17 namespace po=boost::program_options; 18 19 // output vector. 20 template <typename T> 21 ostream& operator<<(ostream& os, const vector<T>& v) 22 { 23 copy(v.begin(), v.end(), ostream_iterator<T>(os, " ")); 24 return os; 25 } 26 27 int main(int argc, char*argv[]) 28 { 29 try 30 { 31 po::options_description desc("general descriptions."); 32 desc.add_options() 33 ("help", "generate help information") 34 ("input-file", po::value<vector<string> >(), "input files") 35 ("link-file,l", po::value<vector<string> >(), "link file"); 36 37 po::variables_map vm; 38 po::store(po::parse_command_line(argc, argv, desc), vm); 39 po::notify(vm); 40 41 if(vm.count("help")) 42 { 43 cout<<desc<<endl; 44 return 1; 45 } 46 47 if(vm.count("input-file")) 48 { 49 cout<<"Input files: "<<vm["input-file"].as<vector<string> >() 50 <<"\n"; 51 } 52 53 if(vm.count("link-file")) 54 { 55 cout<<"Link file: "<<vm["link-file"].as<vector<string> >() 56 <<"\n"; 57 } 58 } 59 catch(exception& e) 60 { 61 cout<<e.what()<<endl; 62 return -1; 63 } 64 65 return 0; 66 } 67 程序第20行重載了<<運算符,用于輸出vector數組. 第31行定義一個選項描述組件,然后添加允許的選項,add_options()方法返回一個特定對象,該對象重載了()運算.link-file選項指定了短名l,這樣--link-file與-l一個意思. 第37行定義一個存儲器組件對象vm. 第38行分析器parse_command_line將選項描述存儲至vm,這里用到的分析器很簡單,后面會介紹更復雜的應用. 接下來的代碼就是比對vm中存放的選項了,簡單吧,很好理解.下面是運行截圖,編譯需要添加boost program_options庫,即-lboost_program_option  對于input-file選項,每次都要輸出--input-file真的很麻煩,能不能用compiler main.cpp呢,當然可以.這種選項叫做positional option, 在第36行處加上如下代碼: 1 po::positional_options_description p; 2 p.add("input-file", -1); 3 修改第38行,我們要用到功能更強大的command_line_parse,改成如下: 1 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); 編譯運行:看下結果吧  先到這里吧,接下來再看從文件中讀選項:)
2011年1月11日
boost any庫可以在如下三方面改善你的程序:(1)任意類型的類型安全存儲以及安全的取回;(2)在標準庫容器中存放不同類型的方法;(3)可以在無須知道類型的情況下傳送類型。 1 boost::any a; //定義any對象 2 a=std::string("boost any"); //any重載了模板賦值函數 3 a=3.1415; 4 a=15; 5 6 std::string s("any type"); 7 boost::any b(s); //any的模板構造函數 8 從any對象中取出存放數據要借助普通模板函數any_cast,取回數據也很簡單. 1 string ss=boost::any_cast<std::string>(b); 如果類型不符any_cast會拋出一個bad_any_cast異常,該異常繼承自std::bad_cast.同時any對象有type()成員函數,可以比較類型后再進行類型轉換. 1 2 if(a.type()==typeid(int)) 3 { 4 int i=boost::any_cast<int>(a); 5 //do something 6 } 7 else if(a.type()==typeid(std::string)) 8 { 9 std::string s=boost::any_cast<std::string>(a); 10 //do something 11 } 12 else 13 { 14 try 15 { 16 double d=boost::any_cast<double>(a); 17 //do something 18 } 19 catch(std::bad_cast& bc) 20 { 21 std::cout<<"Oops!"; 22 //do something 23 } 24 } 25 說明:any類成員函數empty()用于判斷對象中是否為空,在用any存放指針時要特別注意,any不保證指針非空,即存放空指針時empty()返回還是false.看如下代碼片段便知: 1 int *p=0; 2 a=p; 3 if(!a.empty()) 4 { 5 cout<<"a is not empty.\n"; 6 } 7 else 8 { 9 cout<<"a is empty.\n"; 10 } 11 輸出結果為 a is not empty.所以我們要額外判斷指針是否為空. 1 if(!a.empty()) 2 { 3 if(boost::any_cast<int*>(a) != 0) 4 cout<<"a is not empty.\n"; 5 else 6 cout<<"null pointer.\n"; 7 } 8 else 9 { 10 cout<<"a is empty.\n"; 11 } 12 any存放類指針支持多態.
2011年1月10日
boost progress包括progress_timer, progress_display,分別用于輸出程序運行的時間和顯示運行進度. 1
2 #include <boost/progress.hpp>
3
4 #include <iostream>
5 #include <vector>
6
7 using std::cout;
8 using std::endl;
9 using std::vector;
10 using boost::progress_display;
11 using boost::progress_timer;
12
13 int main()
14 {
15 vector<int> v;
16 int i;
17 for(i=0; i<10; i++)
18 v.push_back(i);
19
20 progress_display display(v.size());
21
22 vector<int>::iterator it;
23 progress_timer elapsed;
24 for(it=v.begin(); it!=v.end(); ++it)
25 {
26 //do something
27 ++display;
28 }
29
30 cout<<"elapsed time: ";
31 return 0;
32 } 程序運行結果截圖: 說明:progress_display重載了operator++,progress_timer在定義時開始計時,對象析構時輸出所耗時間.
|