类的自定义流操纵器

发布于 2024-08-02 18:57:04 字数 706 浏览 2 评论 0原文

我正在尝试编写一个简单的审计类,它通过运算符 << 获取输入并在收到如下所示的自定义操纵器后编写审核:

class CAudit
{
public:
    //needs to be templated
    CAudit& operator << ( LPCSTR data ) {
        audittext << data;
        return *this;
    }

    //attempted manipulator
    static CAudit& write(CAudit& audit) { 
        //write contents of audittext to audit and clear it
        return audit; 
    }

private:
    std::stringstream audittext;
};

//to be used like
CAudit audit;
audit << "Data " << data << " received at " << time << CAudit::write;

我认识到代码中的重载运算符不会返回流对象,但想知道是否仍然可以使用类似操纵器的语法。目前编译器看到的是“<<”作为二进制右移运算符。

感谢您的任何意见, 帕特里克

I am trying to write a simple audit class that takes input via operator << and writes the audit after receiving a custom manipulator like this:

class CAudit
{
public:
    //needs to be templated
    CAudit& operator << ( LPCSTR data ) {
        audittext << data;
        return *this;
    }

    //attempted manipulator
    static CAudit& write(CAudit& audit) { 
        //write contents of audittext to audit and clear it
        return audit; 
    }

private:
    std::stringstream audittext;
};

//to be used like
CAudit audit;
audit << "Data " << data << " received at " << time << CAudit::write;

I recognise that the overloaded operator in my code does not return a stream object but was wondering if it was still possible to use a manipulator like syntax. Currently the compiler is seeing the '<<' as the binary right shift operator.

Thanks for any input,
Patrick

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

转身以后 2024-08-09 18:57:04

要使其工作,您必须添加运算符 << 的重载对于函数,
而不是从中调用函数:

 class CAudit
 {
  //...other details here as in original question

  CAudit& operator << (CAudit & (*func)(CAudit &))
  {
        return func(*this);
  }
 };

 CAudit audit;
 audit << "some text" << CAudit::write;

To make it work you have to add overload of operator << for functions,
than call the function from it:

 class CAudit
 {
  //...other details here as in original question

  CAudit& operator << (CAudit & (*func)(CAudit &))
  {
        return func(*this);
  }
 };

 CAudit audit;
 audit << "some text" << CAudit::write;
格子衫的從容 2024-08-09 18:57:04

二进制移位运算符和流运算符是相同的运算符。为您的类重载运算符+以在 std::cout 上写入“Hello world”是完全合法的(尽管这是一个非常糟糕的主意)。就像 C++ 标准作者决定重载运算符<< 一样。对于流来说就像写入流一样。
你没有写清楚你的问题是什么。我的猜测是编译错误。在这种情况下最好的办法是引用错误消息。如果我是对的,问题是,您只定义了运算符<<对于 LPCSTR,然后您希望它在右侧工作函数对象。
你用了“操纵者”这个词,但你误解了一些东西。流操纵器(来自 STL 的流)是一个对其写入的流执行某些操作的函数。它之所以起作用只是因为这种重载:

ostream& operator<< (ostream& ( *pf )(ostream&));

它接受一个函数并将其应用于流。
同样你需要:

CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
{
  return (*pf)(audit);
}

Binary shift operator and stream operator is the same operator. It is completely legal to overload operator+ for your class to write "Hello world" on std::cout (although it is a very bad idea). The same way C++ standard authors decided to overload operator<< for streams as writing to the stream.
You didn't write clearly what is your problem. My guess is compilation error. The best thing in this case is to quote the error message. If I am right, the problem is, that you defined only operator<< for LPCSTR, and then you want it to work function object on the right side.
You use word "manipulator", but you misunderstand something. Manipulator for a stream (stream from STL) is a function that performs some actions on the stream it is written to. And it works only because of this overload:

ostream& operator<< (ostream& ( *pf )(ostream&));

which takes a function and applies it to a stream.
Similarly you need:

CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
{
  return (*pf)(audit);
}
慕烟庭风 2024-08-09 18:57:04

这不就是

class CAudit
{
public:
    template< typename T >
    CAudit& operator<<( const T& data )
    {
        audittext << data;
        return *this;
    }

    class write {};

    void operator<<( const write& data )
    {
        /* whatever */
    }

private:
    std::stringstream audittext;
};

你想要的吗?

Wouldn't this

class CAudit
{
public:
    template< typename T >
    CAudit& operator<<( const T& data )
    {
        audittext << data;
        return *this;
    }

    class write {};

    void operator<<( const write& data )
    {
        /* whatever */
    }

private:
    std::stringstream audittext;
};

do what you want?

旧话新听 2024-08-09 18:57:04

我对跟踪做了一些非常类似的事情,但使用了stringstream。这确保了所有第三方操作员<< () 和操纵器工作。我还使用析构器而不是客户写入操纵器。

class DebugStream
{
public:
    DebugStream(short level, const char * file, int line) {
        sstream << "L" << level << "\t" << file << "\t" << line << "\t";
    }
    ~DebugStream() { write(sstream.str()); }

    std::ostream & stream() { return sstream; }
private:
    std::stringstream sstream;

    DebugStream(const DebugStream &);
    DebugStream & operator=(const DebugStream &);
};

然后可以通过一些宏来实现:

#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO  if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()

并且代码只使用宏

DBG_INFO << "print some debug information";

您不需要特定的写入操纵器将数据刷新到日志文件。当匿名 DebugStream 对象超出范围时(一旦控制离开该行),内容会自动写入。

尽管在这种情况下我通常会避免使用宏,但使用 if 语句意味着您无需构建跟踪行,除非您确实需要它。

通过 stream() 方法返回 ostream 使其适用于全局成员函数,因为匿名对象不能作为非常量引用参数传递。

I do something very similar for tracing, but use a stringstream. This ensures that all 3rd party operator << () and manipulators work. I also use the desctructor instead of the customer write manipulator.

class DebugStream
{
public:
    DebugStream(short level, const char * file, int line) {
        sstream << "L" << level << "\t" << file << "\t" << line << "\t";
    }
    ~DebugStream() { write(sstream.str()); }

    std::ostream & stream() { return sstream; }
private:
    std::stringstream sstream;

    DebugStream(const DebugStream &);
    DebugStream & operator=(const DebugStream &);
};

This is then made available with some macros:

#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO  if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()

And the code just uses the macros

DBG_INFO << "print some debug information";

You don't need a specific write manipulator to flush the data to the log file. When the anonymous DebugStream object goes out of scope (once control leaves the line) the the contents are automatically written.

Although I usually avoid macros in this case the use of the if statement means you don't have the overhead of building the trace line unless you actually require it.

Returning the ostream via the stream() method enables this to work for global member functions, as anonymous objects cannot be passed as non-const reference parameters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文