2013-05-14 41 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