2

我需要在输出流上绘制我的对象,通常是cout. 但我也希望用户能够输入任何具有<<运算符(例如QTextStream)的流,因此不必cout每次都如此。定义此类参数的最简单方法是什么?

所以这就是我想要的,可以编译的东西:

virtual void draw(GeneralOutStream out = std::cout)
{
    out <<  m_name << std::endl;
}

我知道我可以使用模板,(这就是我正在做的 atm。)但我希望会有一个不需要模板的解决方案。但是,模板解决方案工作正常,所以基本上我只是好奇。

4

2 回答 2

2

我可以想到四种方法。

首先,std::ostream作为你的GeneralOutStream,并假设每个人都继承它。也许写一些东西,以QTextStream使其成为std::ostream.

其次,编写一个template接受GeneralOutStream&& out并对其进行操作的方法。这需要在您的标头中公开您的实现。我会推荐这个。非常强烈,但这确实意味着virtual最终变得毫无用处。

第三,编写一个类型擦除,使用构造函数GeneralOutStream在类中公开要与之交互的通用输出流的部分,该template构造函数将传入的泛型类型存储在pImplwithvirtual方法中,然后在对象的实现中使用该类型。这具有运行时开销并且编写起来非常棘手,并且类似于std::function- 除了GeneralOutStream必须处理能够编写整个无数类型的模式!

如果我要编写#3,GeneralOutStream将是一个template需要GeneralOutStream处理的类型序列,然后进行一些元编程以将这些重载准确地暴露给<<. 这变得非常棘手,因为您需要手动复制重载决议。

第四,创建您想要支持的“GeneralOutStream”类型的枚举。使用双分派技术通过virtual方法调用传递对这些类型实例的引用,在另一端解绑它们并调用您的实现template方法,要求实现类处理整个枚举。这个实现比#3 稍微简单一些,限制了可以传递给draw方法的类型,但允许完全访问实现中的类型class

于 2013-06-17T15:30:31.233 回答
0

您想要任何(派生自std::ostream)或任何具有运算符的对象的解决方案<<吗?

在第一种情况下,您可以传递对流对象的引用:

virtual void draw(std::ostream& out = cout) {
    out << m_name << std::endl;
}

传递副本不会编译。

在第二种情况下,主要问题是接口,因为看起来您想将该函数定义为虚拟成员。如果不是这种情况,并且您仍然想要任何对象的解决方案(不是必需的标准ostream,但任何带有操作员<<定义的),您将不得不使用模板。

于 2013-06-17T15:33:54.720 回答