[libcxx] Define istream_iterator equality comparison operators out-of-line

Currently libc++ defines operator== and operator!= as friend functions in the
definition of the istream_iterator class template. Such definition has a subtle
difference from an out-of-line definition required by the C++ Standard: these
functions can only be found by argument-dependent lookup, but not by qualified
lookup.

This patch changes the definition, so that it conforms to the C++ Standard and
adds a check involving qualified lookup to the test suite.

Patch contributed by Mikhail Maltsev.

Differential Revision: https://reviews.llvm.org/D40415

llvm-svn: 320363
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 6f56d3eee85c60f19e937fa72238b5ea2dfe79bd
diff --git a/include/iterator b/include/iterator
index d59d0b4..8b887db 100644
--- a/include/iterator
+++ b/include/iterator
@@ -904,15 +904,37 @@
     _LIBCPP_INLINE_VISIBILITY istream_iterator  operator++(int)
         {istream_iterator __t(*this); ++(*this); return __t;}
 
+    template <class _Up, class _CharU, class _TraitsU, class _DistanceU>
     friend _LIBCPP_INLINE_VISIBILITY
-    bool operator==(const istream_iterator& __x, const istream_iterator& __y)
-        {return __x.__in_stream_ == __y.__in_stream_;}
+    bool
+    operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x,
+               const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y);
 
+    template <class _Up, class _CharU, class _TraitsU, class _DistanceU>
     friend _LIBCPP_INLINE_VISIBILITY
-    bool operator!=(const istream_iterator& __x, const istream_iterator& __y)
-        {return !(__x == __y);}
+    bool
+    operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x,
+               const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y);
 };
 
+template <class _Tp, class _CharT, class _Traits, class _Distance>
+inline _LIBCPP_INLINE_VISIBILITY
+bool
+operator==(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
+           const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y)
+{
+    return __x.__in_stream_ == __y.__in_stream_;
+}
+
+template <class _Tp, class _CharT, class _Traits, class _Distance>
+inline _LIBCPP_INLINE_VISIBILITY
+bool
+operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
+           const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __y)
+{
+    return !(__x == __y);
+}
+
 template <class _Tp, class _CharT = char, class _Traits = char_traits<_CharT> >
 class _LIBCPP_TEMPLATE_VIS ostream_iterator
     : public iterator<output_iterator_tag, void, void, void, void>