stringformat with constexpr if
#include <string> | |
#include <iostream> | |
#include <memory> | |
/** | |
* Convert all std::strings to const char* using constexpr if (C++17) | |
*/ | |
template<typename T> | |
auto convert(T&& t) { | |
if constexpr (std::is_same<std::remove_cv_t<std::remove_reference_t<T>>, std::string>::value) { | |
return std::forward<T>(t).c_str(); | |
} | |
else { | |
return std::forward<T>(t); | |
} | |
} | |
/** | |
* printf like formatting for C++ with std::string | |
* Original source: https://stackoverflow.com/a/26221725/11722 | |
*/ | |
template<typename ... Args> | |
std::string stringFormatInternal(const std::string& format, Args&& ... args) | |
{ | |
size_t size = snprintf(nullptr, 0, format.c_str(), std::forward<Args>(args) ...) + 1; | |
if( size <= 0 ){ throw std::runtime_error( "Error during formatting." ); } | |
std::unique_ptr<char[]> buf(new char[size]); | |
snprintf(buf.get(), size, format.c_str(), args ...); | |
return std::string(buf.get(), buf.get() + size - 1); | |
} | |
template<typename ... Args> | |
std::string stringFormat(std::string fmt, Args&& ... args) { | |
return stringFormatInternal(fmt, convert(std::forward<Args>(args))...); | |
} | |
int main() { | |
std::string s = "a"; | |
const std::string cs = "b"; | |
const char* cc = "c"; | |
int i = 1; | |
const int i2 = 2; | |
using namespace std::literals; | |
std::cout << stringFormat("%s %s %s %s %s %d %d %d \n", s, cs, cc, "d", "e"s, i, i2, 3); | |
return 0; | |
} |
This comment has been minimized.
This comment has been minimized.
Thanks @iFreilicht, I updated it. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Hi! I just updated my answer on SO to throw an exception in case the formatting failed. Depending on the error-code, this could lead to a huge buffer being allocated.
The only things added are
between lines 26 and 27, and an include for the exception:
#include <stdexcept>
This gist is still linked from my answer, so it would be cool if you could update it to keep it in sync :)