2013-05-14 107 views
6

在回答this SO question(更好地閱讀this "duplicate"),我想出了以下解決方案,以運營商的依賴名稱解析:依賴名稱解析及空間std /標準庫

[temp.dep.res]/1:

在解決相關的名稱,從下列來源的名稱被認爲是:

  • 聲明是在模板的定義點可見。
  • 聲明與實例化上下文(14.6.4.1)和定義上下文中的函數參數類型相關聯的名稱空間。
#include <iostream> 
#include <utility> 

// this operator should be called from inside `istream_iterator` 
std::istream& operator>>(std::istream& s, std::pair<int,int>& p) 
{ 
    s >> p.first >> p.second; 
    return s; 
} 

// include definition of `istream_iterator` only after declaring the operator 
// -> temp.dep.res/1 bullet 1 applies?? 
#include <iterator> 

#include <map> 
#include <fstream> 

int main() 
{ 
    std::ifstream in("file.in"); 

    std::map<int, int> pp; 
    pp.insert(std::istream_iterator<std::pair<int, int>>{in}, 
       std::istream_iterator<std::pair<int, int>>{}); 
} 

但鐺++ 3.2和g ++ 4.8不覺得這是運營商(域名解析)。

是否包含 <iterator>定義了「模板的定義點」 istream_iterator

編輯:Andy Prowl指出,這有什麼好做的標準庫,而是用名稱查找(可以通過多個operator>>模仿標準庫,至少在假istream的命名空間一個被證明)。


EDIT2:解決方法:使用[basic.lookup.argdep/2子彈2

#include <iostream> 
#include <utility> 

// can include <iterator> already here, 
// as the definition of a class template member function 
// is only instantiated when the function is called (or explicit instantiation) 
// (make sure there are no relevant instantiations before the definition 
// of the operator>> below) 
#include <iterator> 

struct my_int 
{ 
    int m; 
    my_int() : m() {} 
    my_int(int p) : m(p) {} 
    operator int() const { return m; } 
}; 

// this operator should be called from inside `istream_iterator` 
std::istream& operator>>(std::istream& s, std::pair<my_int,my_int>& p) 
{ 
    s >> p.first.m >> p.second.m; 
    return s; 
} 

#include <map> 
#include <fstream> 

int main() 
{ 
    std::ifstream in("file.in"); 

    std::map<int, int> pp; 
    pp.insert(std::istream_iterator<std::pair<my_int, my_int>>{in}, 
       std::istream_iterator<std::pair<my_int, my_int>>{}); 
} 

當然,你也可以用你自己的pair類型,只要解決方法的介紹定製operator>>的名稱空間中的關聯類。

回答

3

這裏的問題在於,您致電operator >>的地方在std命名空間內,命名空間中的參數類型爲std

只要編譯器能夠在發生調用的名稱空間或其中存在參數類型的名稱空間(在這種情況下都是std名稱空間)中找到operator >>,無論過載是否可行或無法使用分辨率(在名稱查找後執行),它不會在父命名空間中尋找更多的operator >>重載。

不幸的是,您的operator >>居住在全局名稱空間中,因此未找到。

+0

您能否提供參考? :)我渴望在標準中看到這一點 – dyp 2013-05-14 16:43:49

+0

@DyP:我的回答需要編輯;)我會處理它 – 2013-05-14 16:47:37

+0

好吧,我知道了:) [basic.lookup.unqual]/1;因爲這兩種類型都來自'namespace std',所以在關聯的名稱空間/參數相關查找中查找不起作用。 – dyp 2013-05-14 16:53:29