依赖名称解析命名空间 std/标准库
在回答这个问题时(最好阅读这个重复"),我想出了以下解决运算符依赖名称解析的解决方案:
While answering this SO question (better read this "duplicate"), I came up with the following solution to dependent name resolution of an operator:
[temp.dep.res]/1:
[temp.dep.res]/1:
在解析依赖名称时,会考虑来自以下来源的名称:
In resolving dependent names, names from the following sources are considered:
- 在模板定义点可见的声明.
- 来自与实例化上下文 (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 没有找到这个操作符(名称解析).
But clang++ 3.2 and g++ 4.8 don't find this operator (name resolution).
包含
难道不是定义了模板的定义点"istream_iterator
?
Doesn't the inclusion of <iterator>
define the "point of definition of the template" istream_iterator
?
正如 Andy Prowl 指出的那样,这与标准库无关,而是与名称查找(可以通过模拟具有多个 operator>>
的标准库来证明,至少一个位于假 istream
的命名空间中).
As Andy Prowl points out, this has nothing to do with the Standard Library, but rather with name lookup (can be proven by mimicking the Standard Library with multiple operator>>
, at least one in the namespace of the fake istream
).
Edit2:一种解决方法,使用 [basic.lookup.argdep]/2 bullet 2
A workaround, using [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
类型,只要解决方法在自定义operator>>
的命名空间中引入关联的类即可.
Of course, you can also use your own pair
type, as long as the workaround introduces an associated class in the namespace of the custom operator>>
.
推荐答案
这里的问题是你调用 operator >>
的点是在 内部的某个地方std
命名空间,参数类型所在的命名空间为 std
.
The problem here is that the point where your call to operator >>
is being made is somewhere inside the std
namespace, and the namespace where the types of the arguments live is std
.
只要编译器可以在调用发生的命名空间或参数类型所在的命名空间(两者都是 std
命名空间在这种情况下),无论它是否适用于重载解析(在名称查找之后执行),它都不会费心寻找 operator > 的更多重载.>
在父命名空间中.
Provided the compiler can find an operator >>
in either the namespace where the call occurs or the namespace where the types of the arguments live (both are the std
namespace in this case), no matter whether it is viable or not for overload resolution (which is performed after name lookup), it won't bother looking for more overloads of operator >>
in parent namespaces.
不幸的是,您的 operator >>
位于全局命名空间中,因此找不到.
Unfortunately, your operator >>
lives in the global namespace and is, therefore, not found.
相关文章