如何重载运算符<<(double const&) in an inherited std::stringstream?

问题描述 投票:0回答:1

我想覆盖

operator<<
,这样:

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

将产生输出:

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

我尝试了什么

压倒一切

既然像这样打印

double
就可以了,所以我大胆地实现了:

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

这不起作用,因为编译器会解释歧义(因为该运算符已经定义)。

继承

就像一开始一样,我可以继承

std::stringstream
并只需替换我的
customstringstream
的该运算符的定义:

#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.

演示

c++ operator-overloading stringstream
1个回答
1
投票

无论你怎么想,继承通常都不是问题。无论如何,我不会从流派生(通常不建议从 STL 类型继承,尽管流允许这样做)。 对于您的情况,有一个更可重用的解决方案,制作一个辅助格式化对象(演示:https://onlinegdb.com/PKtw7P3E8)。

至少使用这种(C++17)方法,您仍然可以混合正常格式和科学格式(并且在代码中仍然有一个中心点,您可以在其中管理格式应该是什么样子)。 对于 C++20,有一个格式库可以帮助您使用自定义格式化程序

#include <iostream>
#include <sstream>

template<typename type_t>
struct as_scientific
{
    explicit as_scientific(type_t& v) : value{v}{};
    type_t value;
};

template<typename type_t>
std::ostream& operator<<(std::ostream& os, const as_scientific<type_t>& scientific)
{
    os << std::scientific << "((" << typeid(type_t).name() << ")(" <<  scientific.value << ")";
    return os;
}

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

    // or directly
    std::cout << as_scientific{d} << "\n";
}
© www.soinside.com 2019 - 2024. All rights reserved.