C++:使用函数指针重载<<运算符

C++: Overloading << operator with function pointers

本文关键字:lt 运算符 重载 指针 函数 C++      更新时间:2023-10-16

我有一个类"stampstream",它本质上是像"cout"一样工作的。下面的两个函数在类之外。这是有效的部分。

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(stampstream& (*x)(void))
    {
        //code
    }
    //code
};
stampstream& endr()
{
    //nocode
}
stampstream& (*endrow)(void)=endr;

主要:

stampstream s;
s << "teststring1" << endrow;

请注意,"endrow"本质上是"endl"。这部分工作得非常好,编译和执行都有正确的输出。现在,我正试图使<lt;使用另一个可能的行(int)函数。这是不起作用的部分。同样,它是与上面相同的类的一部分,下面的2个函数在该类之外。

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(stampstream& (*r)(int y))
    {
        //code
    }
    //code
};
stampstream& ro(int y)
{
    //nocode
}
stampstream& (*row)(int)=ro;

主要:

s << "teststring2" << row(5);

这是我得到的错误:

error: invalid user-defined conversion from ‘stampstream’ to ‘stampstream& (*)(int)’ [-fpermissive]

我划船做错了什么?

问题是在中

s << "teststring2" << row(5);

函数调用的优先级高于<<,因此它调用row指向的函数,然后尝试将其返回值(stampstream &)传递给operator<<

你想要的是

s << "teststring2" << row;

这并不调用函数,而是将指针传递给operator<<。在函数中,当您想要调用x时,您需要提供参数。

听起来,试图做的是使用一个函数row创建一个函子对象,然后将其传递给operator<<。您可以在C++11中使用lambda:来实现这一点

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(std::function<stampstream&(void)> r)
    {
        //code
    }
    //code
};
std::function<stampstream&(void)> row(int x)
{
    return [x]()->stampstream & {
        //code
    }
}

您可以称之为:

s << "teststring2" << row(5);

首先调用row,它构造一个lambda并返回它(但还没有运行其中的代码)。函子被传递给operator<<,当该函数调用r时,它将调用lambda中的代码(它可以引用x参数,该参数由值绑定,因此被复制到lambda中。)

由于Chris已经回答了您的问题,我想建议您当前方法的替代方案:

  1. 您的stampstream类应该使用一个专门的std::streambuf来写出overflow()内部的戳。不需要扩展std::ostream并重新实现输入运算符。有关如何执行此操作的示例,请参阅本线程。

  2. 您似乎在使用类似于endrowrow的操纵器。对于在调用站点不接受参数的操纵器,已经存在运算符重载。您可以让endrow获取并返回类型为std::ostream&的对象。对于row,您可以让它返回一个重载插入器的类,以允许您想要的语法:

    struct row_impl
    {
        row_impl(int row) : row(row) { }
        // Write out the row and return the stream
        friend std::ostream& operator<<(std::ostream& os, row_impl const& rimpl);
    private:
        int row;
    };
    std::ostream& operator<<(std::ostream& os, row_impl const& rimpl)
    {
        // This is where the code for your original row() function goes
    }
    // write out to and return the stampstream instance
    std::ostream& endrow(std::ostream& os);
    row_impl row(int row)
    {
        return row_impl(row);
    }
    

    现在s << endrows << row(5)将在不需要向stampstream类添加任何内容的情况下工作。