Floating point global formatting options

I know that it is not possible to overload (stream) statements for primitive types as follows:

std::ostream & operator<<(std::ostream &stream, const double s) { stream << std::scientific << std::showpos << std::setprecision(15) << std::to_string(s); return stream; } 

What is the preferred way to define global formatting options for primitive types? Note that I want to apply formatting to any type of output stream, and not just to specific streams, for example, std::cout . C ++ 11 solutions are welcome. Any clues?

+5
source share
4 answers

Overloading threads is a bad idea, but you can wrap them. If you want to perform special, but usual preprocessing / post-processing, define a custom (template) class that has the stream as a member (possibly affected by the constructor) and delegates the actual io to this stream after entering the preprocessing and / or does some after processing after.

 class Printer { ostream &ost; Printer(ostream& st): ost(st) { // other initializations ... } Printer& operator << (double d) { ost << std::scientific << std::showpos << std::setprecision(15) << std::to_string(s); return *this; } // others: ostream conversion, other processing... } 
+2
source

You can define your own manipulator for setting stream formats. Your manipulator should correspond to the format expected by the operator << :

 basic_ostream& operator<<( std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) ); 

So for example:

 template <class Char> basic_ostream<Char>& format_double(basic_ostream<Char>& stream) { return stream << std::scientific << std::showpos << std::setprecision(15); } 

Then just do:

 cout << format_double << 2.0; 

References

Notes

There are two formats for manipulators: one accepts the ios_base argument, and the other basic_ostream . You should use later because it is not specified what the return value of setprecision(int) . For example, my compiler (gcc-4.9) returns a struct _Setprecision , holding an integer, and defines a specific << operator for this structure and basic_ostream .

+5
source

The formatting of numeric types (integers and floating point numbers) can be changed by making sure that the streams use a different std::locale . This tool can be used to create formatting for all streams created after installing global std::locale . Existing threads can also be used to use this modified std::locale on imbue() ing.

An example might look something like this:

 class special_num_put : public std::num_put<char> { virtual iter_type do_put(iter_type it, ios_base& fmt, char_type fill, double v) const { fmt.precision(15); fmt.setf(std::ios_base::showpos); fmt.setf(std::ios_base::scientific, std::ios_base::floatfield); return this->std::num_put<char>::do_put(it, fmt, fill, v); } // likewise for all of the other numeric types }; int main() { std::locale::global(std::locale(std::locale(), new special_num_put)); std::cout.imbue(std::locale()); // deal with existing stream // likewise for all other preexisting streams } 

Please note that I agree with the earlier remark that you should not do anything like that.

+2
source

To expand fjardon's answer , you can create a default format for any type you want to use with a template, for example

 cout << formatted(2.0) << ' ' << formatted(1.4,6) << ' ' << formatted(2.3f) 

uses different prefixes, etc. This can be implemented through

 namespace io_formatting { template<typename Tp> struct manipulator { Tp val; int prec; manipulator(Tp x, int p=std::numeric_limits<Tp>::digits10) : val(x), prec(p) {} }; template<typename X> inline std::ostream& operator<<(std::ostream&o, manipulator<X> const&m) { return o << std::scientific << std::showpos << std::setprecision(m.prec) << m.val; } } template<typename Tp> io_formatting::manipulator<Tp> formatted(Tp x) { return {x}; } template<typename Tp> io_formatting::manipulator<Tp> formatted(Tp x, int p) { return {x,p}; } 

You can use specialization and / or SFINAE to distinguish between different types (floating point, integral, complex ...).

0
source

Source: https://habr.com/ru/post/1232953/


All Articles