依赖名称解析&命名空间std /标准库 [英] Dependent name resolution & namespace std / Standard Library

查看:139
本文介绍了依赖名称解析&命名空间std /标准库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回答此SO问题(更好地阅读这个重复),我想出了以下解决方案来依赖名称解析操作符:



[temp.dep。 res] / 1:


在解析依赖名称时,会考虑以下来源的名称:




  • 在模板定义点可见的声明。

  • 与函数参数类型相关联的命名空间声明实例化上下文(14.6.4.1)和定义上下文。




  #include< iostream> 
#include< utility>

//这个操作符应该从`istream_iterator`里面调用
std :: istream& operator>>(std :: istream& s,std :: pair< int,int>& p)
{
s> p.first>> p.second;
return s;
}

//仅在声明运算符后才包含`istream_iterator'的定义
// - > 1项目符号1适用?
#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



编辑:As Andy Prowl 指出,这与标准库无关,而是与名称查找(可以通过模仿标准库多个 operator>> ,至少在假的 istream 的命名空间中有一个。






Edit2:使用[basic.lookup.argdep] / 2 bullet 2的解决方法

  #include< iostream> 
#include< utility>

//可以包括< iterator>已经在这里,
//作为类模板成员函数的定义
//仅当函数被调用(或显式实例化)时实例化
//(确保没有相关在定义之前的实例化
//的运算符>>下面)
#include< iterator>

struct my_int
{
int m;
my_int():m(){}
my_int(int p):m(p){}
operator int }
};

//这个操作符应该从`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> );
}

当然,您也可以使用自己的

$

解决方案

这里的问题是,您调用 operator>> 的点是 std 命名空间中的某处,以及参数的类型为 std 的命名空间。



如果编译器可以在调用发生的命名空间中找到 operator>> 参数live(在这种情况下都是 std 命名空间),无论它是否可行或重载解析(在之后查找),它不会在父命名空间中寻找更多的重载 operator>>



不幸的是,您的 operator>> 住在全局命名空间,因此找不到。 / p>

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:

In resolving dependent names, names from the following sources are considered:

  • Declarations that are visible at the point of definition of the template.
  • Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.

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

But clang++ 3.2 and g++ 4.8 don't find this operator (name resolution).

Doesn't the inclusion of <iterator> define the "point of definition of the template" istream_iterator?

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

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>>.

解决方案

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.

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.

Unfortunately, your operator >> lives in the global namespace and is, therefore, not found.

这篇关于依赖名称解析&amp;命名空间std /标准库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆