在回答这个 SO 问题时(最好阅读这个 "duplicate"),我想出了以下对运算符的依赖名称解析的解决方案:
[温度.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>>{} );
}
但是 clang++ 3.2 和 g++ 4.8 没有找到这个操作符(名称解析)。
包含不<iterator>
定义“模板的定义点”istream_iterator
吗?
编辑:正如Andy Prowl所指出的,这与标准库无关,而是与名称查找有关(可以通过operator>>
在 fake 的命名空间中模拟标准库中的多个,至少一个来证明istream
)。
Edit2:一种解决方法,使用 [basic.lookup.argdep]/2 bullet 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
类型,只要变通方法在 custom 的命名空间中引入关联类即可operator>>
。