[英]Range-based for loops and ADL
C ++ 0x標准工作草案聲明(第6.5.4節)以下關於在基於范圍的for循環中隱含的begin()和end()調用:
使用參數依賴查找(3.4.2)查找'begin'和'end'。 出於此名稱查找的目的,名稱空間std是關聯的名稱空間。
我讀這個的方式,這意味着為begin()和end()調用設置的重載決議包括以下所有內容:
那是對的嗎?
g ++ 4.6的行為似乎與這種解釋不一致。 對於此代碼:
#include <utility>
template <typename T, typename U>
T begin(const std::pair<T, U>& p);
template <typename T, typename U>
U end(const std::pair<T, U>& p);
int main()
{
std::pair<int*, int*> p;
for (int x : p)
;
}
它給出了以下錯誤:
adl1.cpp: In function 'int main()':
adl1.cpp:12:18: error: No match for 'begin(pair<int *, int *> &)'
adl1.cpp:12:18: candidate is:
/usr/local/lib/gcc/i686-pc-linux-
gnu/4.6.0/../../../../include/c++/4.6.0/initializer_list:86:38: template<
class _Tp> constexpr const _Tp * begin(initializer_list<_Tp>)
adl1.cpp:12:18: error: No match for 'end(pair<int *, int *> &)'
adl1.cpp:12:18: candidate is:
/usr/local/lib/gcc/i686-pc-linux-
gnu/4.6.0/../../../../include/c++/4.6.0/initializer_list:96:36: template<
class _Tp> constexpr const _Tp * end(initializer_list<_Tp>)
這表明,它正在考慮只在空間std重載,而不是在全局命名空間重載。
但是,如果我使用在全局命名空間中聲明的自己的對類,則編譯很好:
template <typename T, typename U>
struct my_pair
{
T first;
U second;
};
template <typename T, typename U>
T begin(const my_pair<T, U>& p);
template <typename T, typename U>
U end(const my_pair<T, U>& p);
int main()
{
my_pair<int*, int*> p;
for (int x : p)
;
}
作為最后的測試,我嘗試將my_pair放在一個單獨的命名空間中:
namespace my
{
template <typename T, typename U>
struct my_pair
{
T first;
U second;
};
}
template <typename T, typename U>
T begin(const my::my_pair<T, U>& p);
template <typename T, typename U>
U end(const my::my_pair<T, U>& p);
int main()
{
my::my_pair<int*, int*> p;
for (int x : p)
;
}
我再次得到錯誤:
adl3.cpp: In function 'int main()':
adl3.cpp:22:18: error: 'begin' was not declared in this scope
adl3.cpp:22:18: suggested alternative:
adl3.cpp:14:35: 'begin'
adl3.cpp:22:18: error: 'end' was not declared in this scope
adl3.cpp:22:18: suggested alternative:
adl3.cpp:17:33: 'end'
因此,它似乎只考慮名稱空間std和其他相關名稱空間中的重載,而不考慮調用站點范圍內的重載(上面列表中的第一個項目符號點)。
這是一個gcc錯誤,還是我誤解了標准?
如果是后者,這是否意味着將std :: pair對象視為基於范圍的for循環中的范圍是不可能的(不會重載std :: begin()和std :: end(),如果我不是錯誤是不允許的)?
我首先報告說這對我來說就像一個gcc bug。 現在看來,甚至環路規范的這一部分還不清楚,並且委員會已經開始進行調查。
看起來基於范圍的for循環規則很快就會發生變化:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3257.pdf
而且我不確定會選擇N3257中列出的哪個選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.