简体   繁体   中英

Is the std::istream type EqualityComparable?

My question would have a boolean answer: yes or not. Whichever it would be, can someone explain how the following code is compiled by both GNU-g++ 4.9.2 and clang 3.5, while GNU-g++ 5.1.1 no longer accepts it, claiming that there is no matching operator== ?

And how it could be changed, for this last compiler, in order to have the same results ie to have the operator>> able to distinguish, in such a simple way, whether it is called by the standard input stream or by something else?

  # include <iostream>
  # include <fstream>

  struct S {};

  std::istream& operator >> (std::istream& i, S& s)
   {
    if(i == std::cin) std::clog << "this is standard input\n";
    else std::clog << "this is some other input stream\n";

    return i;
    }

  int main(int narg, const char ** args)
   {
    S s;
    std :: cin >> s;
    std::ifstream inp(args[1]);
    inp >> s;
    }
  // to be executed with the name of an existing
  // disk file on the command line....

No. There's no operator== that operates on std::istream objects.

Your being able to compare two std::istream s is an unfortunate consequence caused by the conversion function of std::istream , specifically operator void* . In the expression i == std::cin , both i and std::cin are implicitly converted to void* , and the resulting values are compared. This is not really meaningful. This conversion function was removed in C++11 (replaced by an explicit conversion function, which won't be called in this situation), so if you enable the C++11 mode, the code will not compile.

As is stated here , if you want to check whether the reference i refers to std::cin , you can use &i == &std::cin .

Standard C++ streams don't have == , > , < operators because they are not very meaningful in that context: what should "stream a is > than stream b" mean?

However, it shouldn't matter what type of istream you're dealing with: as long as you're not using specific methods defined in descendant classes (like is_open ), base methods are shared (extracting, for instance). Whether you're extracting a string from a istringstream or a ifstream , you just do in >> str and let polymorphism take action.

If you really want to know the polymorphic type of the istream , you can use typeid or, simply, function overloading. In your case, with RTTI( typeid )

if ( typeid(in) == typeid(std::cin) )
    // cin
else
   // another istream type

Using overloading:

std::istream& operator >> (std::istream& i, S& s)
{
     std::clog << "this is standard input\n";   
     return i;
}

std::ifstream& operator>>(std::ifstream& i, S& s)
{
     std::clog << "this is some file input stream\n";
     return i;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM