精華區beta C_and_CPP 關於我們 聯絡資訊
有兩個程式...其中hamming.cpp裡 int distance(vector<int> v1, vector<int> v2); 將兩個vector傳給這個function 然後算兩者的hamming distance 然後在counting.cpp中 vector < vector < int> > L10; ....... for (int m5=0; m5 < L10.size(); m5++) { int d2 = distance ( L10[m5],temp); 把L10[m5] 和temp(兩者皆為 vector < int> ) 傳給distance這個function 但是compile時有錯 好像是說應該用iterator; 請問各位大大 應該怎麼改寫呢?... 謝謝! -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.141.56.156
UNARYvvv:這樣看起來好像沒錯,實際發生錯誤的行再看一下 61.70.137.117 07/28
> -------------------------------------------------------------------------- < 作者: slchen (風城遊子(B)) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Thu Jul 28 23:19:01 2005 ※ 引述《slchen (風城遊子(B))》之銘言: : 有兩個程式...其中hamming.cpp裡 : int distance(vector<int> v1, vector<int> v2); : 將兩個vector傳給這個function 然後算兩者的hamming distance : 然後在counting.cpp中 : vector < vector < int> > L10; : ....... : for (int m5=0; m5 < L10.size(); m5++) : { : int d2 = distance ( L10[m5],temp); : 把L10[m5] 和temp(兩者皆為 vector < int> ) 傳給distance這個function : 但是compile時有錯 : 好像是說應該用iterator; : 請問各位大大 應該怎麼改寫呢?... : 謝謝! 我再把error message po出來好了~~ error 發生在int d2這一行~~ In instantiation of `std::iterator_traits<std::vector<int, std::allocator<int > > >': 31 C:\Dev-Cpp\code\counting.cpp instantiated from here 129 C:\Dev-Cpp\include\c++\3.4.2\bits\stl_iterator_base_types.h no type named `iterator_category' in `class std::vector<int, std::allocator<int> >' 在stl_iterator_base_types.h的第129行是寫這樣的 typedef typename _Iterator::iterator_category iterator_category; 跟iterator有關的..看不太懂error message~~ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.141.56.156 > -------------------------------------------------------------------------- < 作者: khoguan (Khoguan Phuann) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Thu Jul 28 23:48:42 2005 ※ 引述《slchen (風城遊子(B))》之銘言: : ※ 引述《slchen (風城遊子(B))》之銘言: : : 有兩個程式...其中hamming.cpp裡 : : int distance(vector<int> v1, vector<int> v2); : : 將兩個vector傳給這個function 然後算兩者的hamming distance : : 然後在counting.cpp中 : : vector < vector < int> > L10; : : ....... : : for (int m5=0; m5 < L10.size(); m5++) : : { : : int d2 = distance ( L10[m5],temp); : : 把L10[m5] 和temp(兩者皆為 vector < int> ) 傳給distance這個function : : 但是compile時有錯 : : 好像是說應該用iterator; : : 請問各位大大 應該怎麼改寫呢?... 你自訂的函式名稱和標準函式庫的 template<class Init> iterator_traits<InIt>::difference_type distance(InIt first, InIt last); 衝到了!最簡單的解法就是自己的函式改取不一樣的名字。 這個牽涉到 Argument Dependent Lookup (ADL 又稱 Koenig lookup) 像是 max() 或 min() 這種函式名也很容易衝到。 : 我再把error message po出來好了~~ : error 發生在int d2這一行~~ : In instantiation of `std::iterator_traits<std::vector<int, std::allocator<int : 31 C:\Dev-Cpp\code\counting.cpp instantiated from here : 129 C:\Dev-Cpp\include\c++\3.4.2\bits\stl_iterator_base_types.h no type : named `iterator_category' in `class std::vector<int, std::allocator<int> >' : 在stl_iterator_base_types.h的第129行是寫這樣的 : typedef typename _Iterator::iterator_category iterator_category; : 跟iterator有關的..看不太懂error message~~ C++ 和 template 有關的錯誤訊息真是不好懂呀! XD -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.130.208.168
slchen:謝謝啦~~~... 220.141.56.156 07/29
UNARYvvv:哈..話說我先前也看不出來為何會錯..原來是同名 61.70.137.117 07/29
UNARYvvv:不過若是這種情況,不是應該先以引數型別完全相 61.70.137.117 07/29
UNARYvvv:同的 non-template function match 到嗎?? 61.70.137.117 07/29
UNARYvvv:因為照說他們是在同一個 overloaded set 裡面吧 61.70.137.117 07/29
UNARYvvv:不知道為何反而編譯器會選擇 Standard 版的呢?? 61.70.137.117 07/29
otpgoodop:namespace不同.... 59.115.76.234 08/06
> -------------------------------------------------------------------------- < 作者: lichihwu (波特多) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Fri Jul 29 11:56:12 2005 ※ 引述《khoguan (Khoguan Phuann)》之銘言: : ※ 引述《slchen (風城遊子(B))》之銘言: : 你自訂的函式名稱和標準函式庫的 : template<class Init> : iterator_traits<InIt>::difference_type : distance(InIt first, InIt last); : 衝到了!最簡單的解法就是自己的函式改取不一樣的名字。 : 這個牽涉到 Argument Dependent Lookup (ADL 又稱 Koenig lookup) : 像是 max() 或 min() 這種函式名也很容易衝到。 你是不是有using namespace std ? 用stl vector的時候,用std::vector來叫就好了,namespace就是會了避免 這問題才產生的。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 219.84.97.227
khoguan:這樣仍無法解決,請自行依原po寫法實驗看看便知220.130.208.168 07/29
lichihwu:用 ::distance來呼叫就ok... 219.84.97.227 07/29
lichihwu:這是vc在namespace的bug嗎? 219.84.97.227 07/29
lichihwu:還是說namespace有特別用法? 219.84.97.227 07/29
UNARYvvv:用 :: 修飾的話,就會得到 global namespace 那 61.70.137.117 07/29
UNARYvvv:一份 "distance" function 61.70.137.117 07/29
UNARYvvv:所以編譯器就明確知道該選哪個 61.70.137.117 07/29
> -------------------------------------------------------------------------- < 作者: khoguan (Khoguan Phuann) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Sat Jul 30 01:46:24 2005 ※ 引述《khoguan (Khoguan Phuann)》之銘言: : ※ 引述《slchen (風城遊子(B))》之銘言: : : ※ 引述《slchen (風城遊子(B))》之銘言: : : : 有兩個程式...其中hamming.cpp裡 : : : int distance(vector<int> v1, vector<int> v2); : : : 將兩個vector傳給這個function 然後算兩者的hamming distance : : : 然後在counting.cpp中 : : : vector < vector < int> > L10; : : : ....... : : : for (int m5=0; m5 < L10.size(); m5++) : : : { : : : int d2 = distance ( L10[m5],temp); : : : 把L10[m5] 和temp(兩者皆為 vector < int> ) 傳給distance這個function : : : 但是compile時有錯 : : : 好像是說應該用iterator; : : 你自訂的函式名稱和標準函式庫的 : : template<class Init> : iterator_traits<InIt>::difference_type : distance(InIt first, InIt last); : : 衝到了!最簡單的解法就是自己的函式改取不一樣的名字。 : 這個牽涉到 Argument Dependent Lookup (ADL 又稱 Koenig lookup) : 像是 max() 或 min() 這種函式名也很容易衝到。 : 推 UNARYvvv:哈..話說我先前也看不出來為何會錯..原來是同名 61.70.137.117 07/29 : → UNARYvvv:不過若是這種情況,不是應該先以引數型別完全相 61.70.137.117 07/29 : → UNARYvvv:同的 non-template function match 到嗎?? 61.70.137.117 07/29 : → UNARYvvv:因為照說他們是在同一個 overloaded set 裡面吧 61.70.137.117 07/29 : → UNARYvvv:不知道為何反而編譯器會選擇 Standard 版的呢?? 61.70.137.117 07/29 哈,又被 U大 考倒了。(上次在 Programming 版也是) 於是我昨天又到 comp.lang.c++.moderated 去發問。 至今得到近十篇回覆。結果還是沒有確切的答案。 再等等看囉。 不過,先綜合條列一下各種解法: 1. 我原先提的改自己的函式名。這是一種「鋸箭法」啦 XD 2. lichihwu 大大說的,加上 scope resolution operator :: 3. 呼叫時,在函式名字本身前後加上 ( ) 如 int d2 = (distance)(L10[m5],temp); 這樣也能行喔。這種寫法相信很多人沒見過吧 :-) 這樣做可以抑制我前面提到的 ADL -- ※ 發信站: 批踢踢實業坊(ptt.cc) ※ 編輯: khoguan 來自: 220.130.208.168 (07/30 01:46)
UNARYvvv:我是誠心發問的啊~XD 感謝解說~ 61.70.137.117 07/30
UNARYvvv:第三點把函式名稱括起來那招真的沒看過. . 61.70.137.117 07/30
cplusplus:vc7第三種方式還是沒辦法抑制adl o_o 哀~ 140.115.217.14 08/08
> -------------------------------------------------------------------------- < 作者: UNARYvvv (有趣生活) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Mon Aug 8 01:39:14 2005
slchen:謝謝啦~~~... 220.141.56.156 07/29
UNARYvvv:哈..話說我先前也看不出來為何會錯..原來是同名 61.70.137.117 07/29
UNARYvvv:不過若是這種情況,不是應該先以引數型別完全相 61.70.137.117 07/29
UNARYvvv:同的 non-template function match 到嗎?? 61.70.137.117 07/29
UNARYvvv:因為照說他們是在同一個 overloaded set 裡面吧 61.70.137.117 07/29
UNARYvvv:不知道為何反而編譯器會選擇 Standard 版的呢?? 61.70.137.117 07/29
otpgoodop:namespace不同.... 59.115.76.234 08/06
(沒想到過了好幾天居然又有新推文~) 的確 namespace 不同沒錯 但不知道這對我的疑問..有解釋到什麼呢?? 請教一下~謝了 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.70.137.117 ※ 編輯: UNARYvvv 來自: 61.70.137.117 (08/08 01:51) > -------------------------------------------------------------------------- < 作者: khoguan (Khoguan Phuann) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Mon Aug 8 15:17:22 2005 ※ 引述《UNARYvvv (有趣生活)》之銘言: : 推 slchen:謝謝啦~~~... 220.141.56.156 07/29 : 推 UNARYvvv:哈..話說我先前也看不出來為何會錯..原來是同名 61.70.137.117 07/29 : → UNARYvvv:不過若是這種情況,不是應該先以引數型別完全相 61.70.137.117 07/29 : → UNARYvvv:同的 non-template function match 到嗎?? 61.70.137.117 07/29 : → UNARYvvv:因為照說他們是在同一個 overloaded set 裡面吧 61.70.137.117 07/29 : → UNARYvvv:不知道為何反而編譯器會選擇 Standard 版的呢?? 61.70.137.117 07/29 : 推 otpgoodop:namespace不同.... 59.115.76.234 08/06 : (沒想到過了好幾天居然又有新推文~) : 的確 namespace 不同沒錯 : 但不知道這對我的疑問..有解釋到什麼呢?? : 請教一下~謝了 U大還記得這個問題,好學精神,令人感佩。 我先重述並稍微簡化一下原po的問題: #include <vector> #include <iostream> int distance(std::vector<int> v1, std::vector<int> v2) { return v1.size() - v2.size(); } int main() { std::vector<int> v1(3), v2(1); // 再宣告一次,希望讓編譯器選用,結果沒有 :( int distance(std::vector<int> v1, std::vector<int> v2); int d1 = distance(v1, v2); std::cout << "d1=" << d1 << '\n'; return 0; } 編譯錯誤訊息: /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ stl_iterator_base_types.h: In instantiation of `std::iterator_traits<std::vector<int, std::allocator<int> > >': test.cpp:12: instantiated from here /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ stl_iterator_base_types.h:129: error: no type named `iterator_category' in `class std::vector<int, std::allocator<int> >' 問題:為什麼它不直接採用我們自定的 global non-template distance() 就好,卻和 std::distance() 夾纏不清呢? 我在 comp.lang.c++.moderated 上提了這個問題,結果 引來近五十篇討論。這個問題頗為複雜,所以我遲遲未來 向大家報告討論的一些結果,現在既然 U大問起,我試著 整理、說明看看。 真正的問題點並不發生在這個決定要選哪一個函式(也就是 overload resolution)的時間點上,而是在更早之前。也就 是編譯過程根本就還沒進行到 overload resolution的階段 就出錯了。 首先編譯器遇到這個 distance() 函式名稱時,就會開始 去一些地方找它的宣告,哪些地方呢?包括 locally visible 的函式宣告,例如在 local block 裡宣告的,或是在local block 的任何一個外層宣告而沒有被裡層蓋掉(hide)的, 例如global namespace scope 宣告的函式名字。另外, 因為我們呼叫這個 distance() 時,並沒有給它一個 qualifier, 如 ::distance() 或是 std::distance(),這種 unqualified name編譯器還會去一個重要的地方尋找它的宣告,也就是 「宣告參數的型別」所在的 namespace 的地方,這就是 所謂的 ADL(Argument Dependent Lookup)又稱 Koenig lookup, 這是由 Andrew Koenig 所提出的做法。最初是為了解決 overloaded operator 能夠被方便的呼叫使用。這個我就 不再多解釋了。 所以除了原po定義的那個 global scope distance() 以外, 編譯器還會去找到 std namespace 中的 distance(), 因為 原po在呼叫 distance 時,所給的參數是 vector<int> 而 vector 又是宣告於 std namespace 中,所以被直接或間接 include 進來的 std namespace中所有的函式名稱,只要叫 做 distance() 都會被找到。因為找到的 distance() 是個 function template, 所以要先做 template argument deduction 推導成功後,才會將產生的 template instantiation 加到 candidate functions set中,準備進一步做 overload resolution. 現在先將 std::distance() 的宣告式完整的寫出來,方便說明。 template<class InputIterator> typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last); 其中的第二行 typename ...... 一整行就是 return type 在做引數推導(template argument deduction)的過程中,first 和 last 這兩個參數的 InputIterator 被用 vector<int> 來取代完後, return type 接著也要被取代,才能產生一個「正常的」宣告式,以 便在隨後加入 candidate functions set中,於是就變成 iterator_traits<vector<int> >::difference_type 編譯器需要確定這個東西到底是不是有效的 type, 如果最終的結果 是無效的 type 那麼 template argument deduction 就失敗,這個 函式就不會加入 candidate functions set中,這種「失敗」並不會 產生編譯錯誤。 問題是為了確定它有沒有效,編譯器必須先做一個動作,就是用 vector<int> 來 instantiate iterator_traits<> 這個 class template, 然後再看產生的 class 中有沒有宣告 differenct_type 這個型別。 這是 iterator_traits<> 的定義: template<typename _Iterator> struct iterator_traits { typedef typename _Iterator::iterator_category iterator_category; typedef typename _Iterator::value_type value_type; typedef typename _Iterator::difference_type difference_type; typedef typename _Iterator::pointer pointer; typedef typename _Iterator::reference reference; }; 當它用 vector<int> 代入時,就在定義中的第一行發現錯誤: typedef typename vector<int>::iterator_category iterator_category; vector<int>中並沒有宣告 iterator_category,所以編譯器就發出編譯 錯誤的訊息。不 instantiate 則已,一做 instantiate, 這種過程中的 錯誤,編譯器都會發出「抱怨」,不讓你過。 很有趣的,如果我們偷偷的在 vector<> 中加入一個 iterator_category 的 typedef template</*...*/> vector { public: typedef int iterator_category; // ... }; 讓 iterator_traits 的具現化可以順利完成,而且在緊接著的 distance() 的 return type 的取代動作中,也確實有 difference_type可用 (vector<> 中有 difference_type),於是 std::distance() 會加入 overload functions set,但最後仍然還是原po定義的那個 distance() 會被採用。 甚至於,如果我們除了上述那一個動作以外,還多做了一個動作,就是 偷偷的將上面 iterator_traits 定義中的第三行拿掉: //typedef typename _Iterator::difference_type difference_type; 讓 iterator_traits 的具現化可以順利完成,但是在緊接著的 distance() 的 return type 的取代動作中,找不到 difference_type可用,導致 argument type deduction失敗,這種失敗,上面說了,不會造成編譯錯誤。 這是所謂的 SFINAE (Substitution Failure Is Not An Error). 以上的說明,但願能提供不一樣的思考方向。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ※ 編輯: khoguan 來自: 61.227.252.148 (08/08 15:20)
UNARYvvv:真的是太感謝k大了,好豐富的說明啊~ 61.70.137.117 08/08
UNARYvvv:本來也是因為我剛好發現有新推文所以才又回的說 61.70.137.117 08/08
godfat:頭昏,還真複雜 61.224.44.95 08/08
khoguan:嗯,和 template 有關的東西的確好複雜滴。 61.227.252.172 08/09
> -------------------------------------------------------------------------- < 作者: freaky (jon) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Mon Aug 8 18:19:50 2005 事實上這牽涉到 C++ Standard 裡的一個目前處於草案階段的議題 (415. Template deduction does not cause instantiation), 也就是規定不需要在 template deduction 過程中做具現化的動作。 提案人 John Spicer 認為要 compiler 在 template argument deduction 過程中去進行伺機具現化 (speculative instantiations) 是不合理的, 而他所取用的例子剛好就是 function template "std::distance<>()"。 不過他認為正因為這個例子並不在 deduction failure 所列舉的情況之中, compiler 應該回報錯誤。 之後另外一個草案 (488. Local types, overload resolution, and template argument deduction) 就如何處理這個問題提出了三種解決辦法。一是在 overload resolution 時產生 錯誤。方法二是在 type-deduction 時產生錯誤。方法三是除非 overload resolution 的結果需要用到這個無法 instantiate 的 instance,否則不會產生 錯誤。最近一次的開會 (2005年四月) 討論傾向採用第二種方法。 ※ 引述《khoguan (Khoguan Phuann)》之銘言: ...略。 : 真正的問題點並不發生在這個決定要選哪一個函式(也就是 : overload resolution)的時間點上,而是在更早之前。也就 : 是編譯過程根本就還沒進行到 overload resolution的階段 : 就出錯了。 ...略。 : 所以除了原po定義的那個 global scope distance() 以外, : 編譯器還會去找到 std namespace 中的 distance(), 因為 : 原po在呼叫 distance 時,所給的參數是 vector<int> 而 : vector 又是宣告於 std namespace 中,所以被直接或間接 : include 進來的 std namespace中所有的函式名稱,只要叫 : 做 distance() 都會被找到。因為找到的 distance() 是個 : function template, 所以要先做 template argument deduction : 推導成功後,才會將產生的 template instantiation 加到 : candidate functions set中,準備進一步做 overload : resolution. ...略。 : 編譯器需要確定這個東西到底是不是有效的 type, 如果最終的結果 : 是無效的 type 那麼 template argument deduction 就失敗,這個 : 函式就不會加入 candidate functions set中,這種「失敗」並不會 : 產生編譯錯誤。 : 問題是為了確定它有沒有效,編譯器必須先做一個動作,就是用 : vector<int> 來 instantiate iterator_traits<> 這個 class template, : 然後再看產生的 class 中有沒有宣告 differenct_type 這個型別。 ...以下略。 看來目前 gcc 和 EDG-based compiler 的處理方式比較接近方法二, VC.net 2003 則用了第三種方法,也就是本例不會發生編譯錯誤。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 210.80.67.18 > -------------------------------------------------------------------------- < 作者: khoguan (Khoguan Phuann) 看板: C_and_CPP 標題: Re: 請問一個關於iterator的問題... 時間: Mon Aug 8 20:39:52 2005 ※ 引述《freaky (jon)》之銘言: : 事實上這牽涉到 C++ Standard 裡的一個目前處於草案階段的議題 : (415. Template deduction does not cause instantiation), : 也就是規定不需要在 template deduction 過程中做具現化的動作。 : 提案人 John Spicer 認為要 compiler 在 template argument deduction : 過程中去進行伺機具現化 (speculative instantiations) 是不合理的, : 而他所取用的例子剛好就是 function template "std::distance<>()"。 : 不過他認為正因為這個例子並不在 deduction failure 所列舉的情況之中, : compiler 應該回報錯誤。 : 之後另外一個草案 : (488. Local types, overload resolution, and template argument deduction) : 就如何處理這個問題提出了三種解決辦法。一是在 overload resolution 時產生 : 錯誤。方法二是在 type-deduction 時產生錯誤。方法三是除非 overload : resolution 的結果需要用到這個無法 instantiate 的 instance,否則不會產生 : 錯誤。最近一次的開會 (2005年四月) 討論傾向採用第二種方法。 是的,這兩個 core language issues 我也注意到了。 但為了避免治絲益棼,所以未提。 :-) issue #415 和這裡的例子可說並無差別,不過 #488 則有點出入, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#488 它是特別針對 "instantiating a function (template) declaration with a local type as a template type-parameter" 到底該怎麼處理而發。 ^^^^^^^^^^^^ : ※ 引述《khoguan (Khoguan Phuann)》之銘言: : ...略。 : : 真正的問題點並不發生在這個決定要選哪一個函式(也就是 : : overload resolution)的時間點上,而是在更早之前。也就 : : 是編譯過程根本就還沒進行到 overload resolution的階段 : : 就出錯了。 : ...略。 : : 所以除了原po定義的那個 global scope distance() 以外, : : 編譯器還會去找到 std namespace 中的 distance(), 因為 : : 原po在呼叫 distance 時,所給的參數是 vector<int> 而 : : vector 又是宣告於 std namespace 中,所以被直接或間接 : : include 進來的 std namespace中所有的函式名稱,只要叫 : : 做 distance() 都會被找到。因為找到的 distance() 是個 : : function template, 所以要先做 template argument deduction : : 推導成功後,才會將產生的 template instantiation 加到 : : candidate functions set中,準備進一步做 overload : : resolution. : ...略。 : : 編譯器需要確定這個東西到底是不是有效的 type, 如果最終的結果 : : 是無效的 type 那麼 template argument deduction 就失敗,這個 : : 函式就不會加入 candidate functions set中,這種「失敗」並不會 : : 產生編譯錯誤。 : : 問題是為了確定它有沒有效,編譯器必須先做一個動作,就是用 : : vector<int> 來 instantiate iterator_traits<> 這個 class template, : : 然後再看產生的 class 中有沒有宣告 differenct_type 這個型別。 : ...以下略。 : 看來目前 gcc 和 EDG-based compiler 的處理方式比較接近方法二, : VC.net 2003 則用了第三種方法,也就是本例不會發生編譯錯誤。 嗯,GCC, Comeau (on-line), VC. Net 2003 這三種環境 我都試過的。它們都會產生編譯錯誤,都是「抱怨」說 vector<int> 並未提供 iterator_category 這種 type. 方法二,所謂的 "Treat this as a type-deduction failure" 如果真是這樣處理的話,那反而可以通過編譯。因為 type-deduction failure 就會導致那個函式版本被排除在 overload set 之外, 不會有編譯錯誤,即是所謂的 SFINAE. 當然,如果最後找不 到任何符合的函式版本,就會有編譯錯誤,不過,那是「後話」了 ^_^ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.227.252.32