c++ - C++ iostream 的自定义操纵器

标签 c++ string iostream

我想为 ostream 实现一个自定义操纵器,以对插入到流中的下一个项目进行一些操作。例如,假设我有一个自定义操纵器 quote:

std::ostringstream os;
std::string name("Joe");
os << "SELECT * FROM customers WHERE name = " << quote << name;  

操纵器quote 将引用name 以产生:

SELECT * FROM customers WHERE name = 'Joe'

我该如何着手实现它? 谢谢。

最佳答案

向 C++ 流添加操纵器特别困难,因为无法控制操纵器的使用方式。可以将新的语言环境注入(inject)流中,流中安装了控制数字打印方式的方面,但不控制字符串的输出方式。然后问题仍然是如何将引用状态安全地存储到流中。

字符串是使用 std 命名空间中定义的运算符输出的。如果你想改变它们的打印方式,同时保持操纵器的外观,你可以创建一个代理类:

namespace quoting {
struct quoting_proxy {
    explicit quoting_proxy(std::ostream & os):os(os){}

    template<typename Rhs>
    friend std::ostream & operator<<(quoting_proxy const& q, 
                                     Rhs const& rhs) {
        return q.os << rhs;
    }

    friend std::ostream & operator<<(quoting_proxy const& q, 
                                     std::string const& rhs) {
        return q.os << "'" << rhs << "'";
    }

    friend std::ostream & operator<<(quoting_proxy const& q, 
                                     char const* rhs) {
        return q.os << "'" << rhs << "'";
    }
private:
    std::ostream & os;
};

struct quoting_creator { } quote;
quoting_proxy operator<<(std::ostream & os, quoting_creator) {
    return quoting_proxy(os);
}
}

int main() {
    std::cout << quoting::quote << "hello" << std::endl; 
}

适合用于 ostream。如果您想概括,您也可以将其设为模板并接受 basic_stream 而不是普通的 string。在某些情况下,它与标准操纵器具有不同的行为。因为它通过返回代理对象来工作,所以它不适用于

这样的情况
std::cout << quoting::quote; 
std::cout << "hello";

关于c++ - C++ iostream 的自定义操纵器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/535444/

相关文章:

python - 如何仅在字符串中连续时删除重复项?

c++ - Fstream 不保存文件中的最后一个单词,也不从文件中读取

c++ - 什么是 undefined reference / Unresolved external symbol 错误,我该如何解决?

c++ - 如何在 C++/WinRT (`Promise.all` 等效项中等待多个可等待/IAsyncActions)?

c++ - 如何使用 Makefile 规则将 .o 文件放入单独的目录

c++ - 在C++中,如何根据运行时条件构造引用不同istream对象的对象?

c++ - 带有颜色和标题的 std::clog 包装器无法正确打印整数

python - gnuradio `ImportError undefined symbol`

c - 服务器验证凭据(套接字编程)

c - 对 strcmp 感到困惑