Skip to content

Instantly share code, notes, and snippets.

@envp
Last active June 27, 2018 04:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save envp/edd0fd3062c69cdb94d6f56eebf622da to your computer and use it in GitHub Desktop.
Save envp/edd0fd3062c69cdb94d6f56eebf622da to your computer and use it in GitHub Desktop.
Maybe sane string formatting in C++11?
#include <iostream>
#include <string>
#include <sstream>
using StringCIter_t = std::string::const_iterator;
// This is the base case we don't like, how
inline StringCIter_t real_format(const std::string& fmt, std::stringstream& stream)
{
throw std::runtime_error("Too few arguments provided to formatter!");
stream << fmt;
return fmt.cend();
}
template<typename T>
StringCIter_t real_format(const std::string& fmt, std::stringstream& stream, T arg)
{
StringCIter_t cit = fmt.cbegin();
while(cit != fmt.cend())
{
if(*cit == '{')
{
StringCIter_t::value_type c = *cit;
++cit;
// Found somewhere to insert the arg
if(*cit == '}')
{
stream << arg;
++cit;
break;
}
else
{
stream << c << *cit;
}
}
else
{
stream << *cit;
++cit;
}
}
return cit;
}
template<typename T, typename... Ts>
inline StringCIter_t real_format(const std::string& fmt,
std::stringstream& stream, T arg, Ts... rest)
{
StringCIter_t cit = real_format(fmt, stream, arg);
return real_format(std::string(cit, fmt.cend()), stream, rest...);
}
template<typename T, typename... Ts>
inline std::string format(const std::string& fmt, T arg, Ts... rest)
{
std::stringstream stream_;
real_format(fmt, stream_, arg, rest...);
return stream_.str();
}
template<typename T>
inline std::string format(const std::string& fmt, T arg)
{
std::stringstream stream_;
StringCIter_t cit = real_format(fmt, stream_, arg);
if(fmt.cend() != cit)
{
real_format(std::string(cit, fmt.cend()), stream_);
}
return stream_.str();
}
int main()
{
// This should throw a std::runtime_error
// std::cout << format("Hello, {}, {}!", "World") << std::endl;
// This should print `Hello, World, C++ number 1!`
std::cout << format("Hello, {}, C++ number {}!", "World", 1) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment