-->

为什么没有范围,为找到我的开始和结束的的std :: istream_iterator的重载?(Wh

2019-06-25 22:55发布

我有这样的代码

std::ifstream file(filename, std::ios_base::in);
if(file.good())
{
    file.imbue(std::locale(std::locale(), new delimeter_tokens()));
    for(auto& entry : std::istream_iterator<std::string>(file))
    {
        std::cout << entry << std::endl;    
    }
}
file.close();

其中std::istream_iterator<std::string>begin()end()被定义如下

template<class T>
std::istream_iterator<T> begin(std::istream_iterator<T>& stream)
{
    return stream;
}

template<class T>
std::istream_iterator<T> end(std::istream_iterator<T>& stream)
{
    return std::istream_iterator<T>();
}

这就是马克·尼尔森也在博士道博的写在这里 。 唉,代码不能在我的Visual Studio 2012编译错误信息

错误C3312:发现类型“的std :: istream_iterator <_Ty>”没有可调用“开始”功能

错误C3312:发现类型“的std :: istream_iterator <_Ty>”没有可调用的“结束”功能

问:有什么是我还没有发现,臭虫在编译器(不太可能,但以防万一),或者......好吧,任何想法?


这个问题是清理相当大,由作为建议XEO 。 为了提供更多的背景,这是关系到我引用其他问题 #2,我想知道如何使基于行解析清洁剂比普通环。 编码,并从互联网检查,并有点我有一个效果图如下

std::ifstream file(filename, std::ios_base::in);
if(file.good())
{               
    file.imbue(std::locale(std::locale(), new delimeter_tokens()));
    for(auto& entry : istream_range<std::string>(file)
    {
        std::cout << entry << std::endl;    
    }
}
file.close();

但有轻微的障碍我试图补救。 我认为它看起来更自然写在失败编译和不喜欢的代码

for(auto& entry : istream_range<std::string>(file)

我想请记下不同的迭代器。 该delimeter_tokens的定义如下纳瓦兹好心显示在这里 (代码不重复),并istream_range在码合成博客这里 。 我想开始和结束的实现应该工作,如在上述码合成的博客文章公布

最后一条规则(回退到自由站立开始()和end()函数)允许我们非侵入适应现有容器到基于范围for循环接口。

因此,我与所有的(IR)相关背景的问题。

Answer 1:

远程换依赖于ADL如果本地阵列(特殊处理T foo[N]和构件begin / end不会产生任何结果。

§6.5.4 [stmt.ranged] p1

  • 否则, 开始-exprend-EXPRbegin(__range)end(__range) ,分别, 其中beginend中查找与参数相关的查找(3.4.2)。 对于此名称查找的目的,命名空间std是一个关联的命名空间。

你的问题是,的关联的命名空间std::istream_iterator是(显然) namespace std ,而不是全局命名空间。

§3.4.2 [basic.lookup.argdep] p2

对于每个参数类型T在函数调用中,有一组零个或多个相关联的命名空间和一组零个或多个相关联的类来加以考虑。 由类型的函数的参数[...]完全确定命名空间和类的组。

  • 如果T是一个基本的类型,与其相关联的命名空间和类的组都为空。
  • 如果T是一个类类型 (包括工会),其相关联的类别是:类本身; 类,其中它是一个构件,如果有的话; 其直接和间接基类。 其相关的命名空间是其与其关联的类成员的命名空间。 此外,如果T是一个类模板特,其相关联的命名空间和类还包括:与所述类型的提供了一种用于模板类型参数模板参数相关联的命名空间和类[...]。

注意第二个项目符号的最后一个(引用)的一部分。 它主要是指使用一类是全局命名空间为模板参数的成员使代码工作:

#include <iterator>
#include <iostream>

template<class T>
std::istream_iterator<T> begin(std::istream_iterator<T> is){
  return is;
}
template<class T>
std::istream_iterator<T> end(std::istream_iterator<T>){
  return std::istream_iterator<T>();
}

struct foo{};

std::istream& operator>>(std::istream& is, foo){
  return is;
}

int main(){
  for(foo f : std::istream_iterator<foo>(std::cin))
  //                                ^^^
  // make global namespace one of the associated namespaces
    ;
}


Answer 2:

由于参数的依赖查找编译器试图找到begin()end()std命名空间。 如果你把你的功能有,代码编译。

由于名称查找在C一个复杂的问题++我不能完全肯定,如果编译器未能正常行为。



文章来源: Why doesn't range-for find my overloads of begin and end for std::istream_iterator?