Created
November 17, 2023 08:46
-
-
Save ethouris/2b431e1086c2197f516e609b1b4bf023 to your computer and use it in GitHub Desktop.
C++ formatting helper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <iomanip> | |
#include <tuple> | |
template<class TYPE, typename... Args> | |
struct fmt_sender_proxy | |
{ | |
const TYPE& valref; | |
typedef std::tuple<const Args&...> TupleType; | |
TupleType mani; | |
static const size_t manip_size = std::tuple_size<TupleType>::value; | |
template<class OUTSTR, size_t IX> | |
struct fmt_sender_helper | |
{ | |
static void manipulate(OUTSTR& stream, const TupleType& mani) | |
{ | |
stream << std::get<IX>(mani); | |
fmt_sender_helper<OUTSTR, IX+1>::manipulate(stream, mani); | |
} | |
}; | |
template<class OUTSTR> | |
struct fmt_sender_helper<OUTSTR, manip_size> | |
{ | |
static void manipulate(OUTSTR& , const TupleType& ) {} | |
}; | |
template <class OUTSTR> | |
void sendto(OUTSTR& stream) const | |
{ | |
std::ios old(nullptr); | |
old.copyfmt(stream); | |
fmt_sender_helper<OUTSTR, 0>::manipulate(stream, this->mani); | |
stream << valref; | |
stream.copyfmt(old); | |
} | |
}; | |
template<class TYPE, typename... Args> | |
inline fmt_sender_proxy<TYPE, Args...> fmt(const TYPE& val, const Args&... manips) | |
{ | |
return fmt_sender_proxy<TYPE, Args...> { | |
val, | |
std::tuple<const Args&...> { manips... } | |
}; | |
} | |
template<class TR, typename... Args> | |
inline TR& operator<<(TR& ot, const fmt_sender_proxy<Args...>& formatter) | |
{ | |
formatter.sendto(ot); | |
return ot; | |
} | |
int main( int argc, char** argv ) | |
{ | |
const double pi10 = 31.415926536; | |
const double twelve = 12; | |
using namespace std; | |
cout << "default: " << pi10 | |
<< " fixed: " << fmt(pi10, fixed) | |
<< " sci/prec12: " << fmt(pi10, scientific, setprecision(12)) | |
<< " default: " << pi10 | |
<< endl; | |
cout << "default: " << twelve | |
<< " width4: " << fmt(twelve, setw(4), setfill('0')) | |
<< " default: " << twelve | |
<< endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a helper for iostream formatting, which allows you to format values always reliably without leaving the stream in an undefined formatting state, as long as you never use stream manipulators directly. Requires C++11.
This works also in iostream wrapping functions, like this one, for example:
For a value=17 simply use
cout << value
to have it formatted with default flags as "17" andcout << fmt(value, hex, showbase)
to have "0x11". Same for the aboveSprint("flags hex=", fmt(value, hex, showbase), " dec=", value)
.Additionally,
fmt
may be forcefully set the type of the value, if needed in particular case, for example:without the explicitly specified type,
val
would be printed as a character.