2013-05-14 14 views
6

rispondendo this SO question (meglio leggere this "duplicate"), mi si avvicinò con la seguente soluzione per la risoluzione dei nomi a carico di un operatore:Dependent risoluzione dei nomi e namespace std/Standard Biblioteca

[temp.dep.res]/1:

Nella risoluzione nomi dipendenti, i nomi dalle seguenti fonti sono considerati:

  • dichiarazioni che sono visibili al momento della definizione del modello.
  • Dichiarazioni dai namespace associati ai tipi degli argomenti della funzione sia dal contesto di istanziazione (14.6.4.1) che dal contesto di definizione.
#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>>{}); 
} 

Ma clang ++ 3.2 e 4.8 g ++ non trovano questo operatore (risoluzione dei nomi).

L'inclusione di non definisce il "punto di definizione del modello" istream_iterator?

Edit: Come Andy Prowl sottolinea, questo non ha nulla a che fare con la libreria standard, ma piuttosto con la ricerca del nome (può essere provata imitando la libreria standard con più operator>>, almeno uno nello spazio dei nomi del falso istream).


Edit2: Una soluzione, utilizzando [basic.lookup.argdep]/2 proiettile 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>>{}); 
} 

Naturalmente, è anche possibile utilizzare il proprio pair tipo, a condizione che la soluzione introduce un classe associata nello spazio dei nomi dell'abitudine operator>>.

risposta

3

Il problema qui è che il punto in cui viene effettuata la chiamata a operator >> è da qualche parte all'interno dello spazio dei nomi std e lo spazio dei nomi in cui vivono i tipi degli argomenti è std.

A condizione che il compilatore trovi uno operator >> nello spazio dei nomi in cui si verifica la chiamata o nello spazio dei nomi in cui vivono i tipi di argomenti (entrambi sono lo spazio dei nomi std in questo caso), indipendentemente dal fatto che sia valido o meno per il sovraccarico risoluzione (che viene eseguita dopo la ricerca del nome), non si preoccuperà di cercare più sovraccarichi di operator >> negli spazi dei nomi padre.

Sfortunatamente, il tuo operator >> è presente nello spazio dei nomi globale e pertanto non è stato trovato.

+0

Potete fornire un riferimento per favore? :) Sono ansioso di dare un'occhiata allo Standard – dyp

+0

@DyP: La mia risposta ha bisogno di essere modificata;) Ci lavorerò sopra –

+0

Ok, ho capito :) [basic.lookup.unqual]/1; la ricerca in spazi dei nomi associati/ricerca dipendente dall'argomento non funziona qui poiché entrambi i tipi provengono da 'namespace std'. – dyp