c++visual-studioboostg++boost-format

boost::format exception under windows only


I already used boost::format in many case but I found one for which the windows implementation doesn't react as I expected because it throw an exception

boost::bad_format_string: format-string is ill-formed

I use macro to define hexa number output format for different platform:

#if (defined(WIN32) || defined(WIN64))
  #define FORMATUI64X_09       "%09I64X"
  #define FORMATUI64X_016      "%016I64X"
#else
  #if defined __x86_64__
     #define FORMATUI64X_09       "%09lX"
     #define FORMATUI64X_016      "%016lX"
  #else
     #define FORMATUI64X_09       "%09llX"
     #define FORMATUI64X_016      "%016llX"
  #endif
#endif

and call format like below:

string msg = (boost::format("0x"FORMATUI64X_016"(hex) \t %i \t %d \t %s \t %i\t ") % an uint64_t % an int % an uint % a char* % an uint).str();

Remark that I use a syntax working perfectly with a 'fprintf'.

I suppose that it come from the 'uint64_t' format as an hexa, but do you know to write the same line in a way it will work for all platform ?


Solution

  • I64X is not a valid format specification for boost::format (it's Microsoft-specific). The format specification types are not platform-specific. Boost does not use the [sf]printf routines provided by your implementation's runtime, which is why the fact that it works with Visual Studio's fprintf doesn't really affect what boost::format supports. You should be using either %lX or %llX, as your non-Windows clause is doing.

    I would probably just use %llX everywhere and cast output variables to long long, e.g.:

    static_assert(sizeof(unsigned long long) >= sizeof(uint64_t), "long long must be >= 64 bits");
    auto s = (boost::format("0x%016llx") % static_cast<unsigned long long>(u64)).str();
    

    This should work anywhere that unsigned long long is sufficient to represent uint64_t, and you can add a static assertion (as shown) to ensure that.