title: std::ifstream setting fail() even when no error
body: <p>Using GCC 4.7.3 on Cygwin 1.7.24.  Compiler options include: -std=gnu++11 -Wall -Wextra</p>
  
  <p>I am working on a command line application and I needed to be able to load and save a set of strings so I wrote a quick wrapper class around std::set to add load and save methods.</p>
  
  <pre><code>// KeySet.h
  
  #ifndef KEYSET_H
  #define KEYSET_H
  
  #include &lt;cstdlib&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;cerrno&gt;
  #include &lt;cstring&gt;
  
  #include &lt;string&gt;
  #include &lt;set&gt;
  #include &lt;iostream&gt;
  #include &lt;fstream&gt;
  
  inline bool file_exists (const std::string&amp; filename)
  {
  /*
      Utility routine to check existance of a file.  Returns true or false,
      prints an error and exits with status 2 on an error.
  */
      struct  stat buffer;
      int     error = stat(filename.c_str(), &amp;buffer);
      if (error == 0) return true;
      if (errno == ENOENT) return false;
      std::cerr &lt;&lt; "Error while checking for '" &lt;&lt; filename &lt;&lt; "': " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
      exit (2);
  }
  
  class KeySet
  {
  private:
      std::string             filename;
      std::set&lt;std::string&gt;   keys;
  
  public:
      KeySet() {}
      KeySet(const std::string Pfilename) : filename(Pfilename) {}
  
      void set_filename (const std::string Pfilename) {filename = Pfilename;}
      std::string get_filename () {return filename;}
      auto size () -&gt; decltype(keys.size()) {return keys.size();}
      auto cbegin() -&gt; decltype(keys.cbegin()) {return keys.cbegin();}
      auto cend() -&gt; decltype(keys.cend()) {return keys.cend();}
      auto insert(const std::string key) -&gt; decltype(keys.insert(key)) {return keys.insert(key);}
      void load ();
      void save ();
  };
  
  void KeySet::load ()
  {
      if (file_exists(filename)) {
          errno = 0;
          std::ifstream   in (filename, std::ios_base::in);
  
          if (in.fail()) {
              std::cerr &lt;&lt; "Error opening '" &lt;&lt; filename &lt;&lt; "' for reading: " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
              exit (2);
          }
  
          std::string     token;
          if (token.capacity() &lt; 32) token.reserve(32);
  
          while (in &gt;&gt; token) keys.insert(token);
  
          if (!in.eof()) {
              std::cerr &lt;&lt; "Error reading '" &lt;&lt; filename &lt;&lt; "': " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
              exit (2);
          }
  
          in.clear(); // need to clear flags before calling close
          in.close();
          if (in.fail()) {
              std::cerr &lt;&lt; "Error closing '" &lt;&lt; filename &lt;&lt; "': " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
  
              exit (2);
          }
      }
  }
  
  void KeySet::save ()
  {
      errno = 0;
      std::ofstream   out (filename, std::ios_base::out);
  
      if (out.fail()) {
          std::cerr &lt;&lt; "Error opening '" &lt;&lt; filename &lt;&lt; "' for writing: " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
          exit (2);
      }
  
      for (auto key = keys.cbegin(), end = keys.cend(); key != end; ++key) {
          out &lt;&lt; *key &lt;&lt; std::endl;
      }
  
      out.close();
      if (out.fail()) {
          std::cerr &lt;&lt; "Error writing '" &lt;&lt; filename &lt;&lt; "': " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
          exit (2);
      }
  }
  
  #endif
  
  //
  </code></pre>
  
  <p>Here's a quick program to test the load method.</p>
  
  <pre><code>// ks_test.cpp
  
  #include "KeySet.h"
  
  int main()
  {
      KeySet          test;
      std::string     filename = "foo.keys.txt";
  
      test.set_filename(filename);
  
      test.load();
  
      for (auto key = test.cbegin(), end = test.cend(); key != end; ++key) {
          std::cout &lt;&lt; *key &lt;&lt; std::endl;
      }
  }
  </code></pre>
  
  <p>The data file just has "one two three" in it.</p>
  
  <p>When I go to run the test program, I get the following error from my test program:</p>
  
  <pre><code>$ ./ks_test
  Error closing 'foo.keys.txt': No error
  </code></pre>
  
  <p>Both <a href="http://en.cppreference.com/w/cpp/io/basic_ifstream/close" rel="nofollow">cppreference.com</a> and <a href="http://www.cplusplus.com/reference/fstream/ifstream/close/" rel="nofollow">cplusplus.com</a> say that the close method should set the fail bit on error.  The save method works fine, and the load method works correctly if I comment out the error check after the close.  Should this really work or have I misunderstood how close is supposed to work?  Thanks in advance.</p>
  
  <p>Edited to clarify, fix typo's and adjust code per Joachim Pileborg's and Konrad Rudolph's comments.</p>
  
  <p>Edited to add solution to the code.</p>