检测运营商的结束<<序列

时间:2013-06-16 06:55:10

标签: c++ operator-overloading sequence terminator

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

object << argument1 << argument2 << argument3;

假设我重载了运算符&lt;&lt;像这样

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

上面的表达式将按如下方式评估:

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

为了论证,让我们说对象是一个记录器。我将数据流式传输到记录器中。一旦最后一个参数(在这种情况下为argument3,但参数的数量当然没有固定)已经流入对象,我希望对象汇编消息并发布它。我怎么能这样做而不必写这样的东西:

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

谢谢。欢迎任何投入。

3 个答案:

答案 0 :(得分:3)

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

但如果你真的需要你所要求的,你可以这样做:你像往常一样实现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的正常实例的信号,因为它们没有那种方式,并且它们保留了对你Object并且可能会在它们被销毁后尝试使用它们。
  • 如果operator << Object没有抛出异常,你只能安全地使用这种技术,因为它在析构函数中被调用而析构函数不应抛出
  • 由于AutoEnd旨在用作临时对象,并且您只能轻松地使用const &个临时对象,operator <<获取并返回一个常量引用,并且存储Object引用声明为mutable。在我看来,这不是一个糟糕的设计,因为AutoEnd个对象没有任何内部状态(除了Object &)而且调用operator <<的正确性需要是在其他地方保证(即AutoEnd不需要关心它。)
  • 您应该AutoEnd不可复制。

答案 1 :(得分:0)

你不能(除非object在每一行之后被销毁)。像EOM这样的东西很常见。

答案 2 :(得分:0)

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

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

序列的真正结束在哪里?只有你知道,因为你设计和编码它。所以EOM是很好的惯例 - 使用它。