Зависимое разрешение имен & amp; namespace std / Стандартная библиотека

Отвечая этот ТАК вопрос (лучше прочитать этот «дубликат»), Я придумал следующее решение для зависимого разрешения имен оператора:

[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 не находят этот оператор (разрешение имен).

Не включает ли <iterator> определить «точку определения шаблона» istream_iterator?

Изменить: как Энди Проул указывает, что это не имеет ничего общего со стандартной библиотекой, а скорее с поиском имени (можно доказать, подражая стандартной библиотеке с несколькими operator>>хотя бы один в пространстве имен фейка 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>>,

6

Решение

Проблема здесь в том, что точка, где ваш звонок operator >> делается где-то внутри std пространство имен, и пространство имен, в котором живут типы аргументов, std,

При условии, что компилятор может найти operator >> либо в пространстве имен, где происходит вызов, либо в пространстве имен, в котором находятся типы аргументов (оба являются std пространство имен в данном случае), независимо от того, является ли оно жизнеспособным или нет для разрешения перегрузки (которое выполняется после поиск имени), это не будет беспокоить поиск дополнительных перегрузок operator >> в родительских пространствах имен.

К сожалению, ваш operator >> живет в глобальном пространстве имен и, следовательно, не найден.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]