| 265 | // conversions. |
| 266 | template<typename T> |
| 267 | inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, |
| 268 | const char* fmtEnd, const T& value) |
| 269 | { |
| 270 | #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS |
| 271 | // Since we don't support printing of wchar_t using "%ls", make it fail at |
| 272 | // compile time in preference to printing as a void* at runtime. |
| 273 | typedef typename detail::is_wchar<T>::tinyformat_wchar_is_not_supported DummyType; |
| 274 | (void) DummyType(); // avoid unused type warning with gcc-4.8 |
| 275 | #endif |
| 276 | // The mess here is to support the %c and %p conversions: if these |
| 277 | // conversions are active we try to convert the type to a char or const |
| 278 | // void* respectively and format that instead of the value itself. For the |
| 279 | // %p conversion it's important to avoid dereferencing the pointer, which |
| 280 | // could otherwise lead to a crash when printing a dangling (const char*). |
| 281 | const bool canConvertToChar = detail::is_convertible<T,char>::value; |
| 282 | const bool canConvertToVoidPtr = detail::is_convertible<T, const void*>::value; |
| 283 | if(canConvertToChar && *(fmtEnd-1) == 'c') |
| 284 | detail::formatValueAsType<T, char>::invoke(out, value); |
| 285 | else if(canConvertToVoidPtr && *(fmtEnd-1) == 'p') |
| 286 | detail::formatValueAsType<T, const void*>::invoke(out, value); |
| 287 | #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND |
| 288 | else if(detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) /**/; |
| 289 | #endif |
| 290 | else |
| 291 | out << value; |
| 292 | } |
| 293 | |
| 294 | |
| 295 | // Overloaded version for char types to support printing as an integer |