首页 文章

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

提问于
浏览
0

我有一个类“标记流”,基本上打算像'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” . 这部分工作得很好,编译和执行正确的输出 . 现在,我正在尝试用另一个可能的row(int)函数重载<< . 这是不起作用的部分 . 同样,它是上述同一类的一部分,以下两个函数在类之外 .

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]

排怎么办?

2 回答

  • 1

    问题在于

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

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

    你想要的是什么

    s << "teststring2" << row;
    

    这不会调用函数,而是将指针传递给 operator<< . 在该函数内部,当您想要调用 x 时,您需要提供参数 .

    这听起来像你要做的是有一个函数 row ,它创建一个仿函数对象,然后你可以传递给 operator<< . 您可以使用lambda在C 11中执行此操作:

    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 param,它被值绑定,因此被复制到lambda中 . )

  • 2

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

    • 您的 stampstream 类应该使用专门的 std::streambuf 来写出 overflow() 内的图章 . 没有必要扩展 std::ostream 并重新实现输入运算符 . 有关如何执行此操作的示例,see this thread .

    • 你似乎正在使用 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 类添加任何内容即可使用 .

相关问题