我正在图像处理的上下文中学习IO,这是我第一次不得不将流用于二进制文件而不是格式化/文本文件。我正在尝试使用带有模板编程的重载流插入运算符将位图的前 14 个字符读入结构。
#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;
}
我的编译器(g++
(给出错误:
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_;
^~~~~~~~~~~~~~~~~~
我不确定如何准确解释此错误消息。我知道std::fstream
和std::iostream
不兼容,请参阅此相关问题,但我不明白它是否告诉作员正在期待std::basic_ifstream<char>&
并得到了std::basic_istream<char>
,反之亦然。
我也不确定如何解决这个问题。我尝试将模板从
template<typename... Args, typename istream_type = std::basic_istream<Args...>>
自
template<typename... Args, typename istream_type = std::basic_ifstream<Args...>>
但它不会更改错误消息。
如果有人能指出我正确的方向,我将不胜感激。我不确定我是否应该尝试从不同的流类型读取数据,或者我是否应该修改流运算符的规范或模板以使其与我当前的流类型兼容。
提前感谢!
问题是,在你的代码中,这个表达式的类型:
is >> hdr.header_field_[0] >> ...
是std::istream&
.然后,在语句return
,您尝试通过上述类型std::istream&
(base(表达式初始化类型std::ifstream&
(派生(的返回值,这是不可能的。尝试此示例以产生完全相同的错误:
std::ifstream f;
std::istream& ref1 = f; // OK
std::ifstream& ref2 = ref1; // ERROR
一个简单的补救措施是将代码分成 2 行:
is >> hdr.header_field_[0] >> ...;
return is;
另一种选择是向下转换为istream_type&
,但是,这里的语法太复杂了(IMO(。