簡體   English   中英

基於范圍的循環和ADL

[英]Range-based for loops and ADL

C ++ 0x標准工作草案聲明(第6.5.4節)以下關於在基於范圍的for循環中隱含的begin()和end()調用:

使用參數依賴查找(3.4.2)查找'begin'和'end'。 出於此名稱查找的目的,名稱空間std是關聯的名稱空間。

我讀這個的方式,這意味着為begin()和end()調用設置的重載決議包括以下所有內容:

  • begin()和end()的所有重載都在使用基於范圍的for循環的位置的范圍內(特別是,全局命名空間中的所有重載都在范圍內)
  • 命名空間std中begin()和end()的所有重載
  • 在與其參數關聯的其他名稱空間中的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM