C++ 在写入流时执行函数
c++ execute function any time a stream is written to
我有一个简单的 GUI 程序,它使用自定义stringstream
将控制台的输出重定向到 GUI 中的文本字段(在某些情况下)。 现在。每当我按 Enter 时,窗口都会重新绘制,但有可能在其他时间生成输出。 有没有办法向每次在流上使用<<
运算符时执行的stringstream
注册函数?
注意
我应该指出,我不能在我的解决方案中使用C++11。 将编译和运行此内容的计算机将没有可用的 C++11。
就个人而言,我根本不会为此使用std::ostringstream
(甚至std::stringstream
)!相反,我会创建自己的流缓冲区,负责将数据发送到 GUI。也就是说,我将覆盖std::streambuf::overflow()
并std::streambuf::sync()
将当前数据发送到 GUI。为了确保立即发送任何输出,我将设置一个std::ostream
来设置std::ios_base::unitbuf
。实际上,将更改发送到函数非常简单,即,我将实现这一点:
#include <streambuf>
#include <ostream>
#include <functional>
#include <string>
#include <memory>
#include <iostream> // only for testing...
#if HAS_FUNCTION
typedef std::function<void(std::string)> function_type;
#else
class function_type
{
private:
struct base {
virtual ~base() {}
virtual base* clone() const = 0;
virtual void call(std::string const&) = 0;
};
template <typename Function>
struct concrete
: base {
Function d_function;
concrete(Function function)
: d_function(function) {
}
base* clone() const { return new concrete<Function>(this->d_function); }
void call(std::string const& value) { this->d_function(value); }
};
std::auto_ptr<base> d_function;
public:
template <typename Function>
function_type(Function function)
: d_function(new concrete<Function>(function)) {
}
function_type(function_type const& other)
: d_function(other.d_function->clone()) {
}
function_type& operator= (function_type other) {
this->swap(other);
return *this;
}
~function_type() {}
void swap(function_type& other) {
std::swap(this->d_function, other.d_function);
}
void operator()(std::string const& value) {
this->d_function->call(value);
}
};
#endif
class functionbuf
: public std::streambuf {
private:
typedef std::streambuf::traits_type traits_type;
function_type d_function;
char d_buffer[1024];
int overflow(int c) {
if (!traits_type::eq_int_type(c, traits_type::eof())) {
*this->pptr() = traits_type::to_char_type(c);
this->pbump(1);
}
return this->sync()? traits_type::not_eof(c): traits_type::eof();
}
int sync() {
if (this->pbase() != this->pptr()) {
this->d_function(std::string(this->pbase(), this->pptr()));
this->setp(this->pbase(), this->epptr());
}
return 0;
}
public:
functionbuf(function_type const& function)
: d_function(function) {
this->setp(this->d_buffer, this->d_buffer + sizeof(this->d_buffer) - 1);
}
};
class ofunctionstream
: private virtual functionbuf
, public std::ostream {
public:
ofunctionstream(function_type const& function)
: functionbuf(function)
, std::ostream(static_cast<std::streambuf*>(this)) {
this->flags(std::ios_base::unitbuf);
}
};
void some_function(std::string const& value) {
std::cout << "some_function(" << value << ")n";
}
int main() {
ofunctionstream out(&some_function);
out << "hello" << ',' << " world: " << 42 << "n";
out << std::nounitbuf << "not" << " as " << "many" << " callsn" << std::flush;
}
上面代码的相当一部分实际上与手头的任务无关:它实现了std::function<void(std::string)>
的原始版本,以防无法使用C++2011。
如果您不想要那么多调用,您可以关闭std::ios_base::unitbuf
,仅在刷新流时发送数据,例如使用 std::flush
(是的,我知道std::endl
但不幸的是它通常被误用 我强烈建议摆脱它并在真正意味着刷新的地方使用std::flush
)。
您应该创建自己的 streambuf 类。 streambuf 类表示 IO 设备,每个类都处理特定于该类型设备的各种问题。该标准为文件定义了一个 streambuf,为字符串定义了另一个流。网络访问将使用另一个,如果您打算使用流,则输出到 GUI 也应该表示为另一种设备。
编写一个合适的 streambuf 类并非易事,似乎有点晦涩难懂,但那里有资源。C++标准库 - 教程和参考中有一小节介绍这一点。标准C++ IOStreams and locales: Advanced Programmer's Guide and Reference 提供了深入的信息。搜索subclassing basic_streambuf
也会在网上找到一些免费资源。
如果还没有,是否可以从字符串流派生一个子类并重载其流插入运算符以生成事件?
伪代码:
class AlertingStream : public stringstream
{
ostream& operator << (type)
{
for (each listener in listeners)
{
listener.notify();
}
perform insertion;
return *this;
}
}
- 执行函数时导致崩溃的变量
- 在多个时间戳处执行函数
- 程序不会执行函数 c++
- 仅在函数模板中为那些定义了函数的类型执行函数
- 如何在 c++ 的类声明中执行函数?
- 从 std::vector 迭代器中执行函数指针
- 异步 60 秒延迟后C++执行函数?
- 如果发生错误,则返回错误值,否则,继续执行函数
- 执行函数两次
- C++11:如何在 n 秒后在主线程中执行函数
- C++执行函数和 lambda 内部
- 从主线程C 11执行函数调用的线程
- 现代C++执行函数返回指针的方法
- 为什么Win API线程执行函数,而标准线程则没有
- varargs宏以执行函数调用或将其转换为字符串
- 单步执行函数,但不进入VS2017的参数评估
- 加载 Lua 文件并使用变量而不执行函数
- 尽可能在编译时执行函数契约
- 在QT应用程序中创建并执行函数
- 如何使用boostsio_service.post()执行函数并使用数组或指针作为参数