You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在继承std::stringstream时重载operator<<(double const&)?

自定义stringstream实现double类型特殊格式输出

我需要重载operator<<,让以下代码:

double d = 3.0;
mycustomstringstream << "Hello World " << d << "what a nice day.";
std::cout << mycustomstringstream.str() << std::endl;

输出结果为:

Hello World (double)(3.00000000000)what a nice day.

要求:

  • 使用该自定义流时,所有double类型必须以(double)(<数值>)的格式输出
  • 自定义流需具备std::stringstream的全部功能,且不愿完全重新实现流
  • 目的是避免每次输出double都手动调用转换函数,减少重复操作和错误

我的尝试

全局重载

直接实现全局重载:

std::ostream& operator<<(std::ostream& o, double const& d){
  o<<"(double)("<< d << ")";
  return o;
}

编译报错,提示存在歧义(该运算符已在标准库中定义)。

继承重载

尝试继承std::stringstream并为自定义流重载运算符:

#include <sstream>

class MyCustomStringStream: public std::stringstream{};

MyCustomStringStream& operator<<(MyCustomStringStream& o, double const& d){
  o<<"(double)("<< ( (std::stringstream)(o) << d ) << ")";
  return o;
}

出现错误:

error: use of deleted function 'std::__cxx11::basic_stringstream<_CharT, _Traits, _Alloc>::basic_stringstream(const std::__cxx11::basic_stringstream<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'

之后修改为:

#include <iostream>
#include <sstream>

class MyStringStream: public std::stringstream{
    std::stringstream aux;
public:
    MyStringStream& operator<<(double const& d){
        aux.str() = "";
        aux << std::scientific << "(double)(" << d << ")";
        *this << aux.str();
        return *this;
    }
};

int main() {
    double d = 12.3;
    MyStringStream s;
    s << "Hello World " << d << "what a nice day.";
    std::cout << s.str() << std::endl;
}

但输出结果仍为:

Hello World 12.3what a nice day.

解决方案

问题核心:当调用s << d时,编译器会优先匹配标准库中std::ostream& operator<<(std::ostream&, double)的重载,而非你自定义的成员函数——因为std::stringstream继承自std::ostream,链式调用会触发标准版本。

以下是简洁且符合要求的实现方式:

最终代码

#include <iostream>
#include <sstream>
#include <iomanip>

class MyCustomStringStream : public std::stringstream {
public:
    // 优先匹配double类型的重载
    MyCustomStringStream& operator<<(double d) {
        // 调用基类的operator<<,确保格式符合要求
        *static_cast<std::stringstream*>(this) 
            << "(double)(" << std::fixed << std::setprecision(11) << d << ")";
        return *this;
    }

    // 模板重载处理所有其他类型,转发给基类,保留stringstream全部功能
    template<typename T>
    MyCustomStringStream& operator<<(const T& val) {
        *static_cast<std::stringstream*>(this) << val;
        return *this;
    }
};

int main() {
    double d = 3.0;
    MyCustomStringStream mycustomstringstream;
    mycustomstringstream << "Hello World " << d << "what a nice day.";
    std::cout << mycustomstringstream.str() << std::endl;
    return 0;
}

代码说明

  1. 优先级匹配:自定义的operator<<(double)是更具体的重载,会被编译器优先选择,避免触发标准库版本
  2. 完整功能保留:模板化的operator<<处理所有非double类型,直接转发给基类std::stringstream,确保自定义流具备原类的全部功能
  3. 格式控制:使用std::fixed和std::setprecision(11)保证输出的小数位数与示例一致
  4. 避免递归:通过static_cast<std::stringstream*>(this)明确调用基类的输出运算符,防止递归调用自身

输出结果

Hello World (double)(3.00000000000)what a nice day.

内容的提问来源于stack exchange,提问作者GRamon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:30:01