有没有办法使用这些运算符来输入和输出二进制数据?我想这样做的原因是它使代码可读。例如:infile>>filedecrypter>>metadataparser>>audiodecoder>>effects>>soundplayer;
事实上,如果库或您的代码提供了重载operator<<并operator>>使其正常工作,那么这是可以做到的。关于如何做到这一点的简单示例:
class transformer {
public:
virtual std::iostream& transform(std::iostream&) = 0;
};
class noise : public transformer {
public:
virtual std::iostream& transform(std::iostream&) {
/* extract, change and put into again */
}
};
class echo : public transformer {
public:
virtual std::iostream& transform(std::iostream&) {
/* extract, change and put into again */
}
};
std::iostream& operator>>(std::iostream& io, transformer& ts) {
return ts.transform(io);
}
int main() {
std::stringstream data;
std::ifstream file("sound.wav");
noise n; echo e;
data << file.rdbuf();
data >> n >> e;
/* pipelined data now ready to be played back */
}
Run Code Online (Sandbox Code Playgroud)
使用 pure 的问题std::istream是您会读取,但随后您将无法将转换后的数据放回管道中的下一步。因此我std::iostream在这里使用。这种方法似乎效率不高,因为每个操作员>>调用都会提取整个数据,然后再次放入。
要采用更高效的方式进行流式传输,需要创建一个expression template. 这意味着,在operator>>调用时,您还没有进行转换,但您返回的表达式类型将记录其类型内的操作链:
typedef transform< echo< noise< istream > > > pipeline;
std::ifstream file("file.wav");
pipeline pipe(file);
int byte = pipe.get();
Run Code Online (Sandbox Code Playgroud)
就是这种类型的一个例子。管道的结构被解码为类型本身。因此,管道中不再需要虚拟函数。它不是按需构建的,而是在这里使用 typedef 来展示原理。对这样的系统进行编程并不容易。因此,您可能应该研究现有系统,例如 Boost.Iostreams(见下文)。为了让您了解它的样子,这是我刚刚为您编写的一个示例:):
#include <iostream>
template<typename T>
struct transformer {
int get() {
return static_cast<T*>(this)->read();
}
};
struct echot {
template<typename Chain>
struct chain : transformer< chain<Chain> > {
Chain c;
int read() {
return c.get() + 1;
}
chain(Chain const& c):c(c) { }
};
} echo;
struct noiset {
template<typename Chain>
struct chain : transformer< chain<Chain> > {
Chain c;
int read() {
return c.get() * 2;
}
chain(Chain c):c(c) { }
};
} noise;
template<typename T>
typename T::template chain<std::istream&> operator>>(std::istream& is, T) {
return typename T::template chain<std::istream&>(is);
}
template<typename T, typename U>
typename U::template chain<T> operator>>(T t, U u) {
return typename U::template chain<T>(t);
}
int main() {
std::cout << (std::cin >> echo >> noise).get() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
此处输入 0 会产生 ASCII 码 48,加 1,再乘以 2,得到值 98,这也是最终输出。我认为您同意这不是初学者想要编写的代码。所以也许可以考虑一下boost。
Boost 有一个复杂的 iostreams 库,可以做很多事情。我相信您会找到适合的东西。Boost.Iostreams