4

有没有办法使用这些运算符来输入和输出二进制数据?我想这样做的原因是它使代码可读。例如:infile >> filedecrypter >> metadataparser >> audiodecoder >> effects >> soundplayer;

4

4 回答 4

3

需要明确的是,您是否打算复制 iostream 的语义?因为看起来你提出了一些不同的建议。在您给出的示例中:

infile >> filedecrypter >> metadataparser >> audiodecoder >> effects >> soundplayer;

在 iostreams 中,这里的意思是从 infile 读取到 filedecrypter 直到你得到空白,然后从 infile 读取到 metadataparser 直到更多的空白,等等。

看起来您提出了一些不同的建议,其中 metadataparser 从 filedecrypter 读取,从 metadataparser 读取 audiodecoder 等。在这种情况下,我认为您的问题的答案需要稍微限定一下。

你能用运算符 >>来表达这个结构吗?可能是的。

您可以为此使用 iostreams吗?可能不是

我建议您在说 A >> B 时澄清它的含义。也许首先将其表达为常规方法而不是运算符重载,这可能会澄清问题。

于 2008-11-23T22:18:33.910 回答
2

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 */
}

使用 pure 的问题std::istream在于您会阅读,但是您无法将转换后的数据放回管道中的下一步。因此我在std::iostream这里使用。这种方法似乎效率不高,因为每个 operator>> 调用都会提取整个数据,然后再次放入。

要拥有一种更高效的流式传输方式,那就是创建一个expression template. 这意味着,当operator>>被调用时,您还没有进行转换,但您返回的表达式类型将记录其类型内的操作链:

typedef transform< echo< noise< istream > > > pipeline;
std::ifstream file("file.wav");
pipeline pipe(file);
int byte = pipe.get();

将是这种类型的一个例子。管道的结构被解码为类型本身。因此,管道中不再需要虚函数。不是按需构建的,这里使用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;
}

此处输入 0 得到 ASCII 码 48,加 1,再乘以 2,得到值 98,最终也输出。我认为您同意这不是初学者想要编写的代码。所以也许考虑提升。

Boost 有一个复杂的 iostreams 库,它可以做很多事情。我相信你会找到适合这个的东西。Boost.Iostreams

于 2008-11-23T21:08:33.753 回答
2

当然可以。只需定义您自己的 operator>> 和 operator<< 以便他们做“正确的事”...

我会这样做,所以我会在类中有方法,比如 toStream(ostream& os) 和 fromStream(istream& ),然后定义

istream& operator>> (istream& is, T& t)
{
     t.fromStream(is);
     return t;
}

ostream& operator<< (ostream& os, const T& t)
{
     t.toStream(os);
     return t;
}
于 2008-11-23T21:20:10.797 回答
2

无需使用流来移动数据。您可以创建自己的类来执行此操作。这显示了一个例子。显然,Decrypt 和 MetaDataParser 类可以是具有虚函数的抽象基类,以允许将各种功能插入在一起。

#include <iostream>                                                         
#include <istream>                                                          
using namespace std;                                                        

class Data2                                                                 
{                                                                           
};                                                                          

class Data3                                                                 
{                                                                           
};                                                                          

class Decrypt                                                               
{                                                                         
};                                                                          

class MetaDataParser                                                        
{                                                                           
};                                                                          

Data2& operator>>(istream& in, Decrypt& decrypt)                            
{                                                                           
  return *new Data2;                                                        
}                                                                           

Data3& operator>>(Data2& d2, MetaDataParser& mdp)                           
{                                                                           
  return *new Data3;                                                        
}                                                                           

int main()                                                                  
{                                                                           
  Decrypt decrypt;                                                          
  MetaDataParser mdp;                                                       

  cin >> decrypt >> mdp;                                                    
}                                                                           
于 2008-11-23T22:16:24.567 回答