1

在 C++ 中,您如何以编程方式检测以下形式的序列的结尾:

object << argument1 << argument2 << argument3;

假设我像这样重载了 operator<<

Object& operator<<(Object& object, Argument& argument) {
...
}

上面的表达式将被计算如下:

(((object << argument1) << argument2) << argument3);

为了论证的缘故,我们假设 object 是一个记录器。我将数据流式传输到记录器中。一旦最后一个参数(在这种情况下为argument3,但参数的数量当然不是固定的)已流入对象,我希望对象组装消息并发布它。我怎样才能做到这一点而不必写这样的东西:

object << argument1 << argument2 << argument3 << EOM;

谢谢你。欢迎任何输入。

4

3 回答 3

4

正如其他答案所提到的,使用“消息结束”标记是一个很好的设计。

但是如果你真的需要你所要求的,你可以这样做:你像往常一样实现 EOM 的想法,然后添加这个类:

class AutoEnd
{
private:
    mutable Object & m_obj;

public:
    explicit AutoEnd (Object & obj) : m_obj (obj) {}
    ~AutoEnd () {m_obj << EOM;}

    Object & obj () const {return m_obj;}
};

template <typename T>
AutoEnd const & operator << (AutoEnd const & ae, T && arg)
{
    ae.obj() << std::forward<T>(arg);
    return ae;
}

你可以像这样使用它:

Object object;
...
AutoEnd(object) << argument1 << argument2 << argument3;

这将做你想做的事。一些注意事项:

  • 您显然仍然可以EOM在添加后使用显式方法AutoEnd。这使您可以更灵活地使用任何有意义的方法。
  • 这种技术的关键是 的析构函数AutoEnd,它将在实例化它的行的末尾被调用。
  • 您可以比上面更好地实现它。AutoEnd最重要的是,将 的构造函数设为私有或以某种方式向用户发出他们不应该创建 的普通实例的信号是一个好主意AutoEnd,因为那样的话它们是无用的,它们会保留对 youObject的引用,并且可能会在它们之后尝试使用它们被摧毁。
  • operator <<如果forObject不抛出异常,您只能安全地使用此技术,因为它是在析构函数内部调用的,而析构函数不应该 throw
  • 由于AutoEnd被设计为用作临时对象,并且您只能const &轻松使用临时对象,operator <<获取并返回一个常量引用,并且存储的Object引用被声明为mutable. 在我看来,这不是一个糟糕的设计,因为对象没有任何AutoEnd内部状态(除了Object &operator <<AutoEnd
  • 你应该使AutoEnd不可复制。
于 2013-06-16T07:39:35.887 回答
0

你不能(除非object在每一行之后被破坏)。有类似的东西是很常见的EOM

于 2013-06-16T07:02:17.593 回答
0

试想一下,为什么序列符号是可能的。它发生了,因为operator<<返回对流的引用。你可以写:

ostream& s = object << argument1;
s << argument2
s << argument3
...

序列的真正结束在哪里?只有你知道,因为你设计和编码它。EOM良好的常见做法也是如此- 使用它。

于 2013-06-16T07:17:21.803 回答