“has<< operator”类型的参数

时间:2013-06-17 15:10:59

标签: c++ io stream iostream

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

所以这就是我想拥有的东西,这是可以比拟的东西:

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

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

2 个答案:

答案 0 :(得分:2)

我可以想到四种方法。

首先,将std::ostream作为GeneralOutStream,并假设每个人都从中继承。也许写一些包含QTextStream的东西,使其成为std::ostream

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

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

如果我要编写#3,GeneralOutStream将是GeneralOutStream,它采用template应该处理的一系列类型,然后进行一些元编程以准确显示那些重载到GeneralOutStream。这非常棘手,因为您需要手动复制重载决策。

Forth,创建要支持的“GeneralOutStream”类型的枚举。使用双调度技术通过<<方法调用传递对这些类型的实例的引用,在另一方面将它们分开并调用您的实现virtual方法,要求实现类处理整个枚举。这个实现比#3稍微不那么棘手,限制了您可以传递给template方法的类型,但允许完全访问实现draw中的类型。

答案 1 :(得分:0)

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

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

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

传递副本不会编译。

在第二种情况下,主要问题是界面,因为它看起来你想要将该函数定义为虚拟成员。如果不是这种情况,并且您仍然需要任何对象的解决方案(不是必需的标准ostream,而是任何定义了运算符<<的解决方案),则必须使用模板