I'm learning about IO in the context of image processing and its the first time ive had to use the streams for binary files rather than formatted/text files. I'm trying to read the first 14 characters of a bitmap into a struct using an overloaded stream insertion operator with template programming.
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
// a struct for the first 14 bytes
struct bmp_header {
// ordered by size (not their order in the file) for efficient packing
uint32_t size_, pixel_data_offset_;
uint16_t reserved_1_, reserved_2_;
char header_field_[2];
};
// overload stream extraction
template<typename... Args, typename istream_type = std::basic_istream<Args...>>
istream_type &operator>>(istream_type &is, bmp_header &hdr) {
return is >> hdr.header_field_[0] >> hdr.header_field_[1] >> hdr.size_ >> hdr.reserved_1_ >> hdr.reserved_2_ >> hdr.pixel_data_offset_;
}
int main(){
// open the stream
std::string ifname {"images/cameraman.bmp"};
std::ifstream ist {ifname, std::ios::in | std::ios::binary};
// instantiate the struct
bmp_header myHeader;
// read into the struct
ist >> myHeader; // error
ist.close();
return 0;
}
My compiler (g++
) gives error:
new.cpp: In instantiation of ‘istream_type& operator>>(istream_type&, bmp_header&) [with Args = {}; istream_type = std::basic_ifstream<char>]’:
new.cpp:29:10: required from here
new.cpp:17:119: error: invalid initialization of reference of type ‘std::basic_ifstream<char>&’ from expression of type ‘std::basic_istream<char>::__istream_type’ {aka ‘std::basic_istream<char>’}
return is >> hdr.header_field_[0] >> hdr.header_field_[1] >> hdr.size_ >> hdr.reserved_1_ >> hdr.reserved_2_ >> hdr.pixel_data_offset_;
^~~~~~~~~~~~~~~~~~
I'm not sure exactly how to interpret this error message. I know that std::fstream
and std::iostream
aren't compatible see this related question , but I don't understand if its telling me that the operator is expecting std::basic_ifstream<char>&
and been given a std::basic_istream<char>
or vice-versa.
I'm also not sure how to fix this. I've tried changing the template from
template<typename... Args, typename istream_type = std::basic_istream<Args...>>
to
template<typename... Args, typename istream_type = std::basic_ifstream<Args...>>
but it makes no change to the error message.
If anyone could point me in the right direction I'd appreciate it. I'm not sure whether i should be trying to read the data from a different stream type, or if I should modify the specification or template for my stream operator to make it compatible with my current stream type.
Thanks in advance!