在C ++中,如何以编程方式检测表单序列的结尾:
object << argument1 << argument2 << argument3;
假设我重载了运算符&lt;&lt;像这样
Object& operator<<(Object& object, Argument& argument) {
...
}
上面的表达式将按如下方式评估:
(((object << argument1) << argument2) << argument3);
为了论证,让我们说对象是一个记录器。我将数据流式传输到记录器中。一旦最后一个参数(在这种情况下为argument3,但参数的数量当然没有固定)已经流入对象,我希望对象汇编消息并发布它。我怎么能这样做而不必写这样的东西:
object << argument1 << argument2 << argument3 << EOM;
谢谢。欢迎任何投入。
答案 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
是很好的惯例 - 使用它。