Home > Enterprise >  std::string formatting like sprintf / printf and also allow for no arguments
std::string formatting like sprintf / printf and also allow for no arguments

Time:12-29

I am trying to solve a problem just like this one: std::string formatting like sprintf: std::string formatting like sprintf

#include <memory>
#include <string>
#include <stdexcept>

template<typename ... Args>
std::string string_format( const std::string& format, Args ... args )
{
    int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... )   1; // Extra space for '\0'
    if( size_s <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
    auto size = static_cast<size_t>( size_s );
    std::unique_ptr<char[]> buf( new char[ size ] );
    std::snprintf( buf.get(), size, format.c_str(), args ... );
    return std::string( buf.get(), buf.get()   size - 1 ); // We don't want the '\0' inside
}

However the problem I am running into is I want to make it work for cases where there is only the const string and no additional args: `string_format( "just a string" ); If I use the linked solution I get a compile time warning: Not a string literal and no format arguments. I tried to make an intercept function to count the args and then only call my function if the arg size is greater than 0, but I dont think the complier is smart enough to realize what I am doing? Example:

template<typename ... Args>
std::string pre_string_format( const std::string& format, Args ... args)
{
   auto s = sizeof...(Args);
   if( s > 0 )
   {
      return string_format( format, std::forward<Args> (args)...);
   }
   else
   {
     std::string retStr = format;
     return retStr;
   }
}

The underlying problem I am trying to solve is to make a print function that intercepts printf (not sprintf) and then appends things to the string before printing and also logs the prints to different files, etc. The solution provided in the link works great for this with a little tweaking, but it fails if there are args other than the string...

CodePudding user response:

if is evaluated at runtime. Even if the compiler could know which branch is taken, all branches are compiled, hence you get the warning. constexpr if is evaluated at compile time. However, you can use a plain overload:

std::string string_format( const std::string& format) { return format; }
  • Related