0

for my assignment I am building a heap, the data for the heap is coming from a file. One of the functions is to get the data, but I am having trouble understanding the ifstream read() function and am getting quite a nasty error because of it this is what I have:

template<class T, class P>
void get_list(vector<T>& v, const char* file_loc, P func) { 
   T data;
   ifstream inFile;

   inFile.open("file_loc");
   if (!inFile) {
      cerr << "Error - unable to open input file\n";
      exit(1);
   }

   inFile.read( &data, sizeof(T));

   while (inFile) {
      inFile.read( &data, sizeof(T));
      insert(v,data,func);
   }

   inFile.close();
}

the error I am receiving is:

prog7.h:53: error: no matching function for call to 
‘std::basic_ifstream<char, std::char_traits<char> >::read(int*, long unsigned int)’
/usr/include/c++/4.3/istream:468: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT,_Traits>::read(_CharT*, std::streamsize) 
[with _CharT = char,   _Traits = std::char_traits<char>]

any help would be much appreciated!

rajh2504
  • 1,266
  • 2
  • 21
  • 37

5 Answers5

4

istream::read takes a char*. You'll need to cast: (char*)&data.

Also, there's a bug in your code. The read can fail even after the stream test passes. The idiomatic solution is this:

while (inFile.read( &data, sizeof(T))) {
   insert(v,data,func);
}

Overall, your code could be made simpler; you can open the file in the constructor and let the destructor close it. Also, I'm wondering about the first read outside the loop; do you do this with the intent to skip the first entry in the file?

template<class T, class P>
void get_list(vector<T>& v, const char* file_loc, P func) { 
   T data;
   ifstream inFile("file_loc");
   if (!inFile) {
      cerr << "Error - unable to open input file\n";
      exit(1);
   }

   inFile.read( &data, sizeof(T));

   while (inFile.read( &data, sizeof(T))) {
      insert(v,data,func);
   }
}
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • Should you prefer C++ casting (`reinterpret_cast`) to C casting? – Diego Sevilla Nov 02 '10 at 23:14
  • @Diego: The purist in me says yes, but the pragmatist in me has never seen any benefit from making such code more verbose. In the last 15 years, I've had one single occasion where I spent about five minutes hunting a suspicious cast that would have taken seconds to find if it had been written as a reinterpret_cast. So, for me, the lifetime cost of not using new-style casts has been about five minutes. Correction: it has now doubled to ten minutes because I just spent about five minutes thinking about and responding to your comment. – Marcelo Cantos Nov 02 '10 at 23:15
  • Haha, I see. Anyway, not exactly a matter of time lost in this or that, but maybe using what's intended for the case. – Diego Sevilla Nov 02 '10 at 23:23
  • @Diego: The two constructs are almost identical WRT intent; one is merely a newer convention than the other. Plus, a key motivation for the new-style casts was to avoid lost time hunting down bogus casts (Stroustrup even cites the ability to grep for them). While I understand and agree, in principle, with this motivation, I've simply never seen the need in practice. Maybe it's just me, because I cut my teeth on old-style casts and learned caution at a tender age. – Marcelo Cantos Nov 02 '10 at 23:32
2

The prototype for std::ifstream::read is

istream& read ( char* s, streamsize n );

So where you have

inFile.read( &data, sizeof(T));

should be

inFile.read( (char*) &data, sizeof(T));

However this assumes you are reading raw bytes from a binary file. If you are parsing a text file with the integers represented in decimal ascii characters you can just use

inFile >> data;
Akusete
  • 10,704
  • 7
  • 57
  • 73
0

You instantiated the template with type int, but there is no overloaded function for read that takes a pointer to an int as it's first parameter. You can explicitly cast to char* using reinterpret_cast.

Jim Brissom
  • 31,821
  • 4
  • 39
  • 33
0

read() expects a char* (i.e. the element type of the underlying stream). So you need to cast the data pointer to char*:

inFile.read( reinterpret_cast<char*>(&data), sizeof(T));
Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
0

You have to convert the pointer to a char* that is what the read is expecting. You have to use reinterpret_cast<char*>(&data) in the read. Note that this is always dangerous, as this conversion is not checked at all, and you have to be really sure that what you're reading is conforming with the T type. The code is not portable among architectures, word sizes, etc.

Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87