【问题标题】:Dependent name resolution & namespace std / Standard Library从属名称解析和命名空间标准/标准库
【发布时间】:2013-05-14 16:32:51
【问题描述】:

在回答this SO question(最好阅读this "duplicate")时,我想出了以下对运算符的依赖名称解析的解决方案:

[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>>{} );
}

但是 clang++ 3.2 和 g++ 4.8 没有找到这个操作符(名字解析)。

是否包含&lt;iterator&gt; 定义了“模板的定义点”istream_iterator

编辑:正如Andy Prowl 指出的那样,这与标准库无关,而是与名称查找有关(可以通过使用多个operator&gt;&gt; 模拟标准库来证明,至少一个在假的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类型,只要变通方法在自定义operator&gt;&gt;的命名空间中引入关联类即可。

【问题讨论】:

    标签: c++ templates c++11 token-name-resolution


    【解决方案1】:

    这里的问题是,您对operator &gt;&gt; 的调用位于std 命名空间内,而参数类型所在的命名空间是std

    只要编译器可以在调用发生的命名空间或参数类型所在的命名空间(在这种情况下都是 std 命名空间)中找到operator &gt;&gt;,无论它是否可行或不是为了重载解析(在名称查找之后执行),它不会费心在父命名空间中寻找更多operator &gt;&gt; 的重载。

    很遗憾,您的 operator &gt;&gt; 位于全局命名空间中,因此找不到。

    【讨论】:

    • 您能提供参考吗? :) 我很想在标准中查找它
    • 好的,我明白了 :) [basic.lookup.unqual]/1;在关联的命名空间/依赖于参数的查找中的查找在这里不起作用,因为这两种类型都来自namespace std
    • AFAIK 唯一关联的命名空间是namespace std,我不想在其中注入运算符。
    • @DyP:哦,好吧,那我误解你的意思了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 2023-03-26
    • 2013-02-08
    • 1970-01-01
    • 2011-11-17
    相关资源
    最近更新 更多