15

Consider the following program:

#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
using namespace std; //just for convenience, illustration only

typedef pair<int, int> point; //this is my specialization of pair. I call it point

istream& operator >> (istream & in, point & p)
{
    return in >> p.first >> p.second;
}

int main()
{
    vector<point> v((istream_iterator<point>(cin)), istream_iterator<point>()); 
    //             ^^^                         ^^^        
    //extra parentheses lest this should be mistaken for a function declaration
}

This fails to compile because as soon as ADL finds operator >> in namespace std it doesn't consider the global scope any more regardless of whether the operator found in std was a viable candidate or not. This is rather inconvenient. If I place the declaration of my operator >> into namespace std (which is technically illegal) the code compiles well as expected. Is there any way to resolve this issue other than make point my own class rather than typedefing it as a specialization of a template in std namespace?

Thanks in advance

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434

1 Answers1

11

Adding an overload of operator>> in namespace std is forbidden, but adding a template specialization is sometimes allowed.

However, there are no user-defined types here, and the operators on standard types are not yours to redefine. Specializing operator>>(istream&, pair<mytype, int>) would be reasonable.


section [namespace.std] (section 17.6.4.2.1 of n3290) says

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

(emphasis mine)

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Does your answer imply that the answer to my question is ***no*** and I should make `point` a separate class? – Armen Tsirunyan Jul 30 '11 at 18:28
  • Speaking for Ben Voigt, i'd say that yes, it does. – Benoît Jul 30 '11 at 18:33
  • @Benoit: By the way, I don't understand that the operators on standard types are not mine to _re_define. There is no operator >> for pair, so I am not _re_defining anything, am I? – Armen Tsirunyan Jul 30 '11 at 18:35
  • @Armen: Can you quote the paragraph from the standard that prohibits the library from providing `operator>>` for `pair`. – Ben Voigt Jul 30 '11 at 18:51
  • 1
    I can't find a quote that says you can't overload an operator on a standard library type. – Dennis Zickefoose Jul 30 '11 at 19:08
  • @Ben: No, but I can assure you that the standard library doesn't say there must be an operator >> for pair – Armen Tsirunyan Jul 30 '11 at 19:35
  • @Dennis: You can't add such an operator to namespace `std`, I added the relevant quote to my answer. – Ben Voigt Jul 30 '11 at 19:42
  • Right, but he isn't doing that. Simply providing such an operator [not within namespace std] is perfectly kosher. It just might not work properly, as he is witnessing. – Dennis Zickefoose Jul 30 '11 at 19:45
  • 2
    @Dennis: Because of ADL, providing an operator outside namespace `std` is useless. I was addressing the point raised in the question about "If I place the declaration of my `operator >>` into namespace `std` (which is technically illegal) the code compiles well as expected." – Ben Voigt Jul 30 '11 at 19:48