I would like to overload operator<< like this:
ostringstream oss;
MyDate a(2000, 1, 2);
oss << dateFormat("%Y/%m/%d") << a;
assert(oss.str() == "2000-01-02");
so that the date at a will be formatted to specific format. How to achieve this?
In order to store custom state in a stream, you need to use the xalloc static function to get a unique index, and then either pword to get a pointer at that index (allocated specifically for each stream it is used on), or iword to get an integer at that index(allocated specifically for each stream it is used on). In your case, you will probably want pword. You can use the pointer returned by pword to point to a dynamically allocated object which stores the formatting information.
struct DateFormatter
{
// The implementation of this class (e.g. parsing the format string)
// is a seperate issue. If you need help with it, you can ask another
// question
static int xalloc_index;
};
int DateFormatter::xalloc_index = std::ios_base::xalloc();
void destroy_date_formatter(std::ios_base::event evt, std::ios_base& io, int idx)
{
if (evt == std::ios_base::erase_event) {
void*& vp = io.pword(DateFormatter::xalloc_index);
delete (DateFormatter*)(vp);
}
}
DateFormatter& get_date_formatter(std::ios_base& io) {
void*& vp = io.pword(DateFormatter::xalloc_index);
if (!vp) {
vp = new DateFormatter;
io.register_callback(destroy_date_formatter, 0);
}
return *static_cast<DateFormatter*>(vp);
}
std::ostream& operator<<(std::ostream& os, const DateFormatter& df) {
get_date_formatter(os) = df;
return os;
}
std::ostream& operator<<(std::ostream& os, const MyDate& date)
{
DateFormatter& df = get_date_formatter(os);
// format output according to df
return os;
}
int main() {
MyDate a ( 2000, 1, 2 );
std::cout << DateFormatter("%Y/%m/%d") << a;
}
This is the standard method. It is terrible, in my opinion. I much prefer an alternative approach, which is to pass the date object together with the formatting as a single object. For example:
class DateFormatter
{
const MyDate* date;
std::string format_string;
DateFormatter(const MyDate& _date, std::string _format_string)
:date(&_date)
,format_string(_format_string)
{}
friend std::ostream& operator<<(std::ostream& os, const DateFormatter& df) {
// handle formatting details here
return os;
}
};
int main() {
MyDate a ( 2000, 1, 2 );
std::cout << DateFormatter(a, "%Y/%m/%d");
}
Or you can do something like that (using static variable):
#include <iostream>
struct MyDate
{
MyDate(int y, int m, int d): year{y}, month{m}, day{d} {}
int year{};
int month{};
int day{};
};
class DateFormatter
{
public:
DateFormatter(const std::string & format)
{
format_ = format;
}
static const std::string & format()
{
return format_;
}
private:
static std::string format_;
};
std::string DateFormatter::format_ = {"Default Format"};
std::ostream & operator<< (std::ostream & stream, const DateFormatter &)
{
return stream;
}
std::ostream & operator<< (std::ostream & stream, const MyDate & date)
{
auto currentFormat = DateFormatter::format();
// some code using current format ...
return stream << currentFormat << " - " << date.year << "/" << date.month << "/" << date.day;
}
int main(void)
{
MyDate date{2016,4,18};
std::cout << date << std::endl;
std::cout << DateFormatter("New format") << date << std::endl;
return 0;
}
Related
How do I do the following with std::cout?
double my_double = 42.0;
char str[12];
printf_s("%11.6lf", my_double); // Prints " 42.000000"
I am just about ready to give up and use sprintf_s.
More generally, where can I find a reference on std::ostream formatting that lists everything in one place, rather than spreading it all out in a long tutorial?
EDIT Dec 21, 2017 - See my answer below. It uses features that were not available when I asked this question in 2012.
std::cout << std::fixed << std::setw(11) << std::setprecision(6) << my_double;
You need to add
#include <iomanip>
You need stream manipulators
You may "fill" the empty places with whatever char you want. Like this:
std::cout << std::fixed << std::setw(11) << std::setprecision(6)
<< std::setfill('0') << my_double;
std::cout << boost::format("%11.6f") % my_double;
You have to #include <boost\format.hpp>
In C++20 you can to do
double my_double = 42.0;
char str[12];
std::format_to_n(str, sizeof(str), "{:11.6}", my_double);
or
std::string s = std::format("{:11.6}", my_double);
In pre-C++20 you can use the {fmt} library that provides an implementation of format_to_n.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
In general, you want to avoid specifying things like 11 and 6 at the
point of output. That's physical markup, and you want logical markup;
e.g. pressure, or volume. That way, you define in a single place
how pressure or volume are formatted, and if that formatting changes,
you don't have to search through out the program to find where to change
the format (and accidentally change the format of something else). In
C++, you do this by defining a manipulator, which sets the various
formatting options, and preferrably restores them at the end of the full
expression. So you end up writing things like:
std::cout << pressure << my_double;
Although I definitly wouldn't use it in production code, I've found the
following FFmt formatter useful for quicky jobs:
class FFmt : public StateSavingManip
{
public:
explicit FFmt(
int width,
int prec = 6,
std::ios::fmtflags additionalFlags
= static_cast<std::ios::fmtflags>(),
char fill = ' ' );
protected:
virtual void setState( std::ios& targetStream ) const;
private:
int myWidth;
int myPrec;
std::ios::fmtflags myFlags;
char myFill;
};
FFmt::FFmt(
int width,
int prec,
std::ios::fmtflags additionalFlags,
char fill )
: myWidth( width )
, myPrec( prec )
, myFlags( additionalFlags )
, myFill( fill )
{
myFlags &= ~ std::ios::floatfield
myFlags |= std::ios::fixed
if ( isdigit( static_cast< unsigned char >( fill ) )
&& (myFlags & std::ios::adjustfield) == 0 ) {
myFlags |= std::ios::internal
}
}
void
FFmt::setState(
std::ios& targetStream ) const
{
targetStream.flags( myFlags )
targetStream.width( myWidth )
targetStream.precision( myPrec )
targetStream.fill( myFill )
}
This allows writing things like:
std::cout << FFmt( 11, 6 ) << my_double;
And for the record:
class StateSavingManip
{
public:
StateSavingManip(
StateSavingManip const& other );
virtual ~StateSavingManip();
void operator()( std::ios& stream ) const;
protected:
StateSavingManip();
private:
virtual void setState( std::ios& stream ) const = 0;
private:
StateSavingManip& operator=( StateSavingManip const& );
private:
mutable std::ios* myStream;
mutable std::ios::fmtflags
mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
};
inline std::ostream&
operator<<(
std::ostream& out,
StateSavingManip const&
manip )
{
manip( out );
return out;
}
inline std::istream&
operator>>(
std::istream& in,
StateSavingManip const&
manip )
{
manip( in );
return in;
}
StateSavingManip.cc:
namespace {
// We maintain the value returned by ios::xalloc() + 1, and not
// the value itself. The actual value may be zero, and we need
// to be able to distinguish it from the 0 resulting from 0
// initialization. The function getXAlloc() returns this value
// -1, so we add one in the initialization.
int getXAlloc();
int ourXAlloc = getXAlloc() + 1;
int
getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1;
assert( ourXAlloc != 0 );
}
return ourXAlloc - 1;
}
}
StateSavingManip::StateSavingManip()
: myStream( NULL )
{
}
StateSavingManip::StateSavingManip(
StateSavingManip const&
other )
{
assert( other.myStream == NULL );
}
StateSavingManip::~StateSavingManip()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags );
myStream->precision( mySavedPrec );
myStream->fill( mySavedFill );
myStream->pword( getXAlloc() ) = NULL;
}
}
void
StateSavingManip::operator()(
std::ios& stream ) const
{
void*& backptr = stream.pword( getXAlloc() );
if ( backptr == NULL ) {
backptr = const_cast< StateSavingManip* >( this );
myStream = &stream;
mySavedFlags = stream.flags();
mySavedPrec = stream.precision();
mySavedFill = stream.fill();
}
setState( stream );
}
#include <iostream>
#include <iomanip>
int main() {
double my_double = 42.0;
std::cout << std::fixed << std::setw(11)
<< std::setprecision(6) << my_double << std::endl;
return 0;
}
For future visitors who prefer actual printf-style format specs with std::ostream, here is yet another variation, based on Martin York's excellent post in another SO question: https://stackoverflow.com/a/535636:
#include <iostream>
#include <iomanip>
#include <stdio.h> //snprintf
class FMT
{
public:
explicit FMT(const char* fmt): m_fmt(fmt) {}
private:
class fmter //actual worker class
{
public:
explicit fmter(std::ostream& strm, const FMT& fmt): m_strm(strm), m_fmt(fmt.m_fmt) {}
//output next object (any type) to stream:
template<typename TYPE>
std::ostream& operator<<(const TYPE& value)
{
// return m_strm << "FMT(" << m_fmt << "," << value << ")";
char buf[40]; //enlarge as needed
snprintf(buf, sizeof(buf), m_fmt, value);
return m_strm << buf;
}
private:
std::ostream& m_strm;
const char* m_fmt;
};
const char* m_fmt; //save fmt string for inner class
//kludge: return derived stream to allow operator overloading:
friend FMT::fmter operator<<(std::ostream& strm, const FMT& fmt)
{
return FMT::fmter(strm, fmt);
}
};
usage example:
double my_double = 42.0;
cout << FMT("%11.6f") << my_double << "more stuff\n";
or even:
int val = 42;
cout << val << " in hex is " << FMT(" 0x%x") << val << "\n";
it's me, the OP, Jive Dadson - five years on. C++17 is becoming a reality.
The advent of variadic template parameters with perfect forwarding has made life so much simpler. The chained madness of ostream<< and boost::format% can be dispensed with. The function oprintf below fills the bill. Work in progress. Feel free to chime in on error-handling, etc...
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string_view>
namespace dj {
template<class Out, class... Args>
Out& oprintf(Out &out, const std::string_view &fmt, Args&&... args) {
const int sz = 512;
char buffer[sz];
int cx = snprintf(buffer, sz, fmt.data(), std::forward<Args>(args)...);
if (cx >= 0 && cx < sz) {
return out.write(buffer, cx);
} else if (cx > 0) {
// Big output
std::string buff2;
buff2.resize(cx + 1);
snprintf(buff2.data(), cx, fmt.data(), std::forward<Args>(args)...);
return out.write(buff2.data(), cx);
} else {
// Throw?
return out;
}
}
}
int main() {
const double my_double = 42.0;
dj::oprintf(std::cout, "%s %11.6lf\n", "My double ", my_double);
return 0;
}
Some great answers already; kudos to those!
This is based on some of them. I have added type assertions for POD types, since they are the only safe types usable with printf().
#include <iostream>
#include <stdio.h>
#include <type_traits>
namespace fmt {
namespace detail {
template<typename T>
struct printf_impl
{
const char* fmt;
const T v;
printf_impl(const char* fmt, const T& v) : fmt(fmt), v(v) {}
};
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, std::ostream& >::type
operator<<(std::ostream& os, const printf_impl<T>& p)
{
char buf[40];
::snprintf(buf, sizeof(buf), p.fmt, p.v, 40);
return os << buf;
}
} // namespace detail
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, detail::printf_impl<T> >::type
printf(const char* fmt, const T& v)
{
return detail::printf_impl<T>(fmt, v);
}
} // namespace fmt
Example usage it as below.
std::cout << fmt::printf("%11.6f", my_double);
Give it a try on Coliru.
The os.pword(index) method is supposed to return current date format specified by a custom manipulator. The result of pword() gets, however, modified by a different stream by it's str(string) method.
ostringstream os;
istringstream is;
CDate f ( 2000, 5, 12 );
os << date_format ( "%Y-%m-%d" ) << f;
is.clear ();
is.str ( "05.06.2003" ); // causes pword() to return "05.06.2003" instead of "%Y-%m-%d"
os.str ("");
os << f;
Class methods:
struct date_format
{
static const int index;
string format;
explicit date_format(const char * fmt)
{
format = string(fmt);
}
friend ostream & operator<<(ostream & s, const date_format & df)
{
s.pword(index) = (void*)df.format.c_str();
return s;
}
};
const int date_format::index = ios_base::xalloc();
class CDate
{
...
friend ostream & operator<<(ostream & os, const CDate & cdate)
{
/* should point to the current date format of os */
const char * ptr = (const char*)os.pword(date_format::index);
...
return os;
}
}
What causes such behaviour and what can be done to avoid it?
You're experiencing undefined behvaior. In your operator<<(ostream & s, const date_format& df) you set s.pword(index) to a pointer to a data member of a temporary date_format instance. Since date_format( "%Y-%m-%d" ) destructs at the end of the expression, your stream is left with a dangling pointer.
Try making a deep copy of the string before you set a pointer to it.
I found this beautiful little helper on this site:
Howto throw std::exceptions with variable messages?
class Formatter
{
public:
Formatter() {}
~Formatter() {}
template <typename Type>
Formatter & operator << (const Type & value)
{
stream_ << value;
return *this;
}
std::string str() const { return stream_.str(); }
operator std::string () const { return stream_.str(); }
enum ConvertToString
{
to_str
};
std::string operator >> (ConvertToString) { return stream_.str(); }
private:
std::stringstream stream_;
Formatter(const Formatter &);
Formatter & operator = (Formatter &);
};
It can be used like
std::string foo(Formatter() << "foo" << 42);
To allow enabling/disabling of the stream input I extended the class with
bool enabled;
enum class status {
active, inactive
};
Formatter& operator << (status s)
{
if (s == status::active) enabled = true;
if (s == status::inactive) enabled = false;
return *this;
}
and changed the input template to if (enabled) stream_ << value;
Now I can do
std::string optional = "";
std::string foo(Formatter()
<< "foo"
<< (optional.empty() ? Formatter::status::inactive : Formatter::status::active)
<< "bar" << optional
<< Formatter::status::active
<< "!");
Now I´m looking for a way to get rid of status and use Formatter::inactive directly instead.
If I have this code
struct Unit{
int coef; //coefficient
int exp; //exponent
};
class Func: private std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, Func);
};
How do I print it out?
I tried using the concept from here: http://www.cplusplus.com/forum/beginner/5074/
But without success:
ostream& operator<<(ostream &output, Func &pol)
{
list<Unit>::iterator i;
for( i = pol.begin(); i != pol.end(); ++i)
{
Unit test = *i;
output << test.coef << " ";
}
return output;
}
And do I initialize it correctly?
Func::Func()
{
Unit test;
test.coef = 0;
test.exp = 0;
Func::push_back(test);
}
Sorry. New to this about inheritance. Though it wasn't hard when it was about the classes I made myself.
Updated code:
struct Unit{
int coef; //coefficient
int exp; //exponent
Unit():coef(0),exp(0){}
};
class Func : public std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, const Func &);
};
Func::Func()
{
Unit test;
Func::push_back(test);
}
ostream& operator <<(std::ostream &output, const Func& pol)
{
for (list<Unit>::const_iterator i = pol.begin(); i != pol.end(); output << i->coef << " " << i->exp << " ", ++i);
return output;
}
It is not clear for me what do you want to do. Is is a requirement that you inherit from an STL list? I wouldn't do it.
But this at least would be a solution.
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator<<(std::ostream &os, Unit const& v)
{
os << v.coef << " " << v.exp << std::endl;
return os;
}
int main()
{
std::list<Unit> myList;
Unit element;
element.coef = 0;
element.exp = 0;
myList.push_back(element);
std::ostringstream os;
for (std::list<Unit>::const_iterator it = myList.begin(); it != myList.end(); ++it)
{
os << *it;
}
std::cout << os.str() << std::endl;
}
With C++11 this could be implemented much nicer, but I don't know what compiler you are using. I did not compile it so far, just hacked it down; so sorry for syntax errors.
First, regarding your printing. You can do it a number of ways, the most robust being defining free operators for each type. Such as:
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
The function is a little more complex. You would be better served to use the list as a member variable and provide an operator for stream insertion for that class. Such as:
#include <iostream>
#include <iterator>
#include <list>
#include <cstdlib>
struct Unit
{
int coef; //coefficient
int exp; //exponent
Unit(int coef, int exp=0)
: coef(coef), exp(exp)
{}
friend std::ostream& operator <<(std::ostream&, const Unit&);
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
class Func
{
public:
std::list<Unit> units;
friend std::ostream& operator <<(std::ostream&, const Func&);
};
std::ostream& operator <<(std::ostream& os, const Func& func)
{
std::copy(func.units.begin(), func.units.end(),
std::ostream_iterator<Unit>(os, " "));
return os;
}
int main()
{
Func func;
func.units.push_back(Unit(3, 2));
func.units.push_back(Unit(2, 1));
func.units.push_back(Unit(1, 0));
std::cout << func << endl;
return EXIT_SUCCESS;
}
Output
3X^2 2X^1 1X^0
Note: I did NOT properly hide members, provide accessors, etc. That I leave to you, but the general idea on how to provide output-stream operators should be obvious. You could significantly further enhance the output operator for a `Unit by:
Not printing exponents of 1
Only printing the coefficient for exponents of 0 (no X),
Not printing a 1 coefficient of any term with an exponent greater than 0
Not printing anything for terms with 0 coefficients.
These tasks I leave to you.
How do I do the following with std::cout?
double my_double = 42.0;
char str[12];
printf_s("%11.6lf", my_double); // Prints " 42.000000"
I am just about ready to give up and use sprintf_s.
More generally, where can I find a reference on std::ostream formatting that lists everything in one place, rather than spreading it all out in a long tutorial?
EDIT Dec 21, 2017 - See my answer below. It uses features that were not available when I asked this question in 2012.
std::cout << std::fixed << std::setw(11) << std::setprecision(6) << my_double;
You need to add
#include <iomanip>
You need stream manipulators
You may "fill" the empty places with whatever char you want. Like this:
std::cout << std::fixed << std::setw(11) << std::setprecision(6)
<< std::setfill('0') << my_double;
std::cout << boost::format("%11.6f") % my_double;
You have to #include <boost\format.hpp>
In C++20 you can to do
double my_double = 42.0;
char str[12];
std::format_to_n(str, sizeof(str), "{:11.6}", my_double);
or
std::string s = std::format("{:11.6}", my_double);
In pre-C++20 you can use the {fmt} library that provides an implementation of format_to_n.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
In general, you want to avoid specifying things like 11 and 6 at the
point of output. That's physical markup, and you want logical markup;
e.g. pressure, or volume. That way, you define in a single place
how pressure or volume are formatted, and if that formatting changes,
you don't have to search through out the program to find where to change
the format (and accidentally change the format of something else). In
C++, you do this by defining a manipulator, which sets the various
formatting options, and preferrably restores them at the end of the full
expression. So you end up writing things like:
std::cout << pressure << my_double;
Although I definitly wouldn't use it in production code, I've found the
following FFmt formatter useful for quicky jobs:
class FFmt : public StateSavingManip
{
public:
explicit FFmt(
int width,
int prec = 6,
std::ios::fmtflags additionalFlags
= static_cast<std::ios::fmtflags>(),
char fill = ' ' );
protected:
virtual void setState( std::ios& targetStream ) const;
private:
int myWidth;
int myPrec;
std::ios::fmtflags myFlags;
char myFill;
};
FFmt::FFmt(
int width,
int prec,
std::ios::fmtflags additionalFlags,
char fill )
: myWidth( width )
, myPrec( prec )
, myFlags( additionalFlags )
, myFill( fill )
{
myFlags &= ~ std::ios::floatfield
myFlags |= std::ios::fixed
if ( isdigit( static_cast< unsigned char >( fill ) )
&& (myFlags & std::ios::adjustfield) == 0 ) {
myFlags |= std::ios::internal
}
}
void
FFmt::setState(
std::ios& targetStream ) const
{
targetStream.flags( myFlags )
targetStream.width( myWidth )
targetStream.precision( myPrec )
targetStream.fill( myFill )
}
This allows writing things like:
std::cout << FFmt( 11, 6 ) << my_double;
And for the record:
class StateSavingManip
{
public:
StateSavingManip(
StateSavingManip const& other );
virtual ~StateSavingManip();
void operator()( std::ios& stream ) const;
protected:
StateSavingManip();
private:
virtual void setState( std::ios& stream ) const = 0;
private:
StateSavingManip& operator=( StateSavingManip const& );
private:
mutable std::ios* myStream;
mutable std::ios::fmtflags
mySavedFlags;
mutable int mySavedPrec;
mutable char mySavedFill;
};
inline std::ostream&
operator<<(
std::ostream& out,
StateSavingManip const&
manip )
{
manip( out );
return out;
}
inline std::istream&
operator>>(
std::istream& in,
StateSavingManip const&
manip )
{
manip( in );
return in;
}
StateSavingManip.cc:
namespace {
// We maintain the value returned by ios::xalloc() + 1, and not
// the value itself. The actual value may be zero, and we need
// to be able to distinguish it from the 0 resulting from 0
// initialization. The function getXAlloc() returns this value
// -1, so we add one in the initialization.
int getXAlloc();
int ourXAlloc = getXAlloc() + 1;
int
getXAlloc()
{
if ( ourXAlloc == 0 ) {
ourXAlloc = std::ios::xalloc() + 1;
assert( ourXAlloc != 0 );
}
return ourXAlloc - 1;
}
}
StateSavingManip::StateSavingManip()
: myStream( NULL )
{
}
StateSavingManip::StateSavingManip(
StateSavingManip const&
other )
{
assert( other.myStream == NULL );
}
StateSavingManip::~StateSavingManip()
{
if ( myStream != NULL ) {
myStream->flags( mySavedFlags );
myStream->precision( mySavedPrec );
myStream->fill( mySavedFill );
myStream->pword( getXAlloc() ) = NULL;
}
}
void
StateSavingManip::operator()(
std::ios& stream ) const
{
void*& backptr = stream.pword( getXAlloc() );
if ( backptr == NULL ) {
backptr = const_cast< StateSavingManip* >( this );
myStream = &stream;
mySavedFlags = stream.flags();
mySavedPrec = stream.precision();
mySavedFill = stream.fill();
}
setState( stream );
}
#include <iostream>
#include <iomanip>
int main() {
double my_double = 42.0;
std::cout << std::fixed << std::setw(11)
<< std::setprecision(6) << my_double << std::endl;
return 0;
}
For future visitors who prefer actual printf-style format specs with std::ostream, here is yet another variation, based on Martin York's excellent post in another SO question: https://stackoverflow.com/a/535636:
#include <iostream>
#include <iomanip>
#include <stdio.h> //snprintf
class FMT
{
public:
explicit FMT(const char* fmt): m_fmt(fmt) {}
private:
class fmter //actual worker class
{
public:
explicit fmter(std::ostream& strm, const FMT& fmt): m_strm(strm), m_fmt(fmt.m_fmt) {}
//output next object (any type) to stream:
template<typename TYPE>
std::ostream& operator<<(const TYPE& value)
{
// return m_strm << "FMT(" << m_fmt << "," << value << ")";
char buf[40]; //enlarge as needed
snprintf(buf, sizeof(buf), m_fmt, value);
return m_strm << buf;
}
private:
std::ostream& m_strm;
const char* m_fmt;
};
const char* m_fmt; //save fmt string for inner class
//kludge: return derived stream to allow operator overloading:
friend FMT::fmter operator<<(std::ostream& strm, const FMT& fmt)
{
return FMT::fmter(strm, fmt);
}
};
usage example:
double my_double = 42.0;
cout << FMT("%11.6f") << my_double << "more stuff\n";
or even:
int val = 42;
cout << val << " in hex is " << FMT(" 0x%x") << val << "\n";
it's me, the OP, Jive Dadson - five years on. C++17 is becoming a reality.
The advent of variadic template parameters with perfect forwarding has made life so much simpler. The chained madness of ostream<< and boost::format% can be dispensed with. The function oprintf below fills the bill. Work in progress. Feel free to chime in on error-handling, etc...
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <string_view>
namespace dj {
template<class Out, class... Args>
Out& oprintf(Out &out, const std::string_view &fmt, Args&&... args) {
const int sz = 512;
char buffer[sz];
int cx = snprintf(buffer, sz, fmt.data(), std::forward<Args>(args)...);
if (cx >= 0 && cx < sz) {
return out.write(buffer, cx);
} else if (cx > 0) {
// Big output
std::string buff2;
buff2.resize(cx + 1);
snprintf(buff2.data(), cx, fmt.data(), std::forward<Args>(args)...);
return out.write(buff2.data(), cx);
} else {
// Throw?
return out;
}
}
}
int main() {
const double my_double = 42.0;
dj::oprintf(std::cout, "%s %11.6lf\n", "My double ", my_double);
return 0;
}
Some great answers already; kudos to those!
This is based on some of them. I have added type assertions for POD types, since they are the only safe types usable with printf().
#include <iostream>
#include <stdio.h>
#include <type_traits>
namespace fmt {
namespace detail {
template<typename T>
struct printf_impl
{
const char* fmt;
const T v;
printf_impl(const char* fmt, const T& v) : fmt(fmt), v(v) {}
};
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, std::ostream& >::type
operator<<(std::ostream& os, const printf_impl<T>& p)
{
char buf[40];
::snprintf(buf, sizeof(buf), p.fmt, p.v, 40);
return os << buf;
}
} // namespace detail
template<typename T>
inline typename std::enable_if<std::is_pod<T>::value, detail::printf_impl<T> >::type
printf(const char* fmt, const T& v)
{
return detail::printf_impl<T>(fmt, v);
}
} // namespace fmt
Example usage it as below.
std::cout << fmt::printf("%11.6f", my_double);
Give it a try on Coliru.