fmtlib / fmt Goto Github PK
View Code? Open in Web Editor NEWA modern formatting library
Home Page: https://fmt.dev
License: Other
A modern formatting library
Home Page: https://fmt.dev
License: Other
I feel that C++11 variadic templates would provide a nice alternative to the streaming syntax that format uses by default.
I've implemented a version of this for my own project, and have had a go at rolling it back into format itself in a more generic form.
The change can be found here: https://github.com/jdale88/format/commit/5a2eb12a783246f87c1a0d1b5355fe8df22ec6d2
At present, the syntax for using that change is as follows (it will accept any number of parameters after the initial format string):
std::string str = fmt::VariadicFormat<fmt::Formatter<>>("Hello {0}", "World");
std::wstring wstr = fmt::VariadicFormat<fmt::Formatter<fmt::NoAction, wchar_t>>(L"Hello {0}", L"World");
I felt it best to discuss this feature before submitting a pull request, as it might be completely unsuitable, or you might want to approach it differently. This bug is really just to open up a discussion about it.
Thanks.
EDIT:
I improved upon that initial commit a bit.
std::string str = fmt::Format("Hello {0}", "World");
std::wstring wstr = fmt::Format(L"Hello {0}", L"World");
Move the generated documentation from the gh-pages branch to the website.
I have tried this code from the examples
fmt::Writer out;
out << "The answer is " << 42 << "\n";
out.Format("({:+f}, {:+f})") << -3.14 << 3.14;
it gives the error:
m:\mmgit\mmcyb\src\mm\cmmaxes.cpp(307): error C2039: 'Format' : is not a member of 'fmt::BasicWriter'
3> with
3> [
3> Char=char
3> ]
Action classes are named inconsistently:
Also there should be clear distinction between writer and action classes.
As the action classes are rarely used explicitly, their names can be fairly verbose, e.g. EmptyAction
, FileWriteAction
, ColoredWriteAction
or something like that.
I tried this with today's master:
fmt::Writer wo;
wo.write ("The answer in hexadecimal is {}", fmt::hex (1337) );
wo << "The answer in hexadecimal is (" << fmt::hex (1337) << ")";
The streaming example with the <<
operator worked fine, but the wo.write()
failed. Shouldn't both be possible? And if not, for what reason?
MSVC build gives a few warnings: https://ci.appveyor.com/project/vitaut/cppformat/build/1.0.40
error C2661: 'fmt::format' : no overloaded function takes 13 arguments
I just built everything from the master today on Win8.1-64 with mingw64 GCC4.9 and running the test EXEs produced a number of "failed" tests. Are they supposed to fail or should all be green and "passed"?
Hi, interesting to set yet another take on this problem :)
I had a look at the docs out of curiosity and have a few comments (maybe I am
just expecting too much, since this library seems to be only a few hours old!)
Support for user-defined types
I wanted to see how you achieved this, but I can't see that it works as
expected. For instance, the following is a compile error:
format::Print("a string: {0}\n") << std::string("asdf");
I thought about implementing positional arguments in tinyformat, and the best
solution I came up with involved a type of variant class as follows:
class Arg
{
public:
virtual void print(std::ostream& out) = 0;
};
template<typename T>
class ArgT : public Arg
{
const T& m_value;
public:
virtual void print(std::ostream& out)
{
out << m_value;
}
};
You'd then construct a std::vector<Arg*> as you sweep through the arguments,
creating an ArgT for the Nth argument. (The could be stack-allocated
in the tinyformat case, though unfortunately not with the << based interface.)
Reordering can then be achived simply using indexing.
In the end I didn't do it because I didn't need the functionality and it would
introduce some extra complexity to tinyformat, which is alreay a lot less tiny
than I would like ;-) It also means a virtual function call per argument which
is less than ideal...
i18n in printf
posix printf does have a notation to support positional arguments for i18n,
and this is implemented in glibc even though it's not in C99. For example,
try out:
printf("%2$s %1$s\n", "first_arg", "second_arg");
Good luck with your implementation!
~Chris
Formatters need a more consistent approach to error reporting. Currently there are three ways to report a format error:
FormatError
immediately.FormatterBase::error_
which is checked at the end of formatting and FormatError
is thrown if it is set.report_error_
(BasicFormatter
only).An important question is whether we want to report errors as soon as they are found or have the ability to override an earlier error with a later, but more important one. The first case is simpler, we just throw FormatError
as soon as an error is found. The second case requires keeping track of an error which complicates the logic.
It seems that Python's str.format
uses the first approach. The only case I found were a later error seem to override an earlier one is the case of unbalanced braces, for example:
>>> '{-1:'.format(42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: unmatched '{' in format
However, this is probably because str.format
processes nested arguments first, so it's not really an exception from the rule.
The printf
function has rudimentary error checking. For example, neither of the following is reported as an error:
printf("%s") printf("%d", "a");
A rare case of an error caught by printf
:
printf("%10000000000d", 0);
This sets errno
to EOVERFLOW
which gives generic error message "Value too large for defined data type".
Considering that
printf
'sI think it makes sense to go with option 1 which is the simplest.
Not sure what is causing this error or what compilerbut a similar problem is described here:
http://heifner.blogspot.co.uk/2008/02/stdmin-and-stdmax.html.
I have manage to get it to compile by:
using namespace std;
and changing std::max to max on line 106 and 662 of format.h.
Here's the original compile error. there are also warnings shown with this fix.
M:\mmgit\mmcyb\inc\format.h(106): error C2589: '(' : illegal token on right side of '::'
1> M:\mmgit\mmcyb\inc\format.h(105) : while compiling class template member function 'void fmt::internal::Array<T,SIZE>::Grow(size_t)'
1> with
1> [
1> T=char,
1> SIZE=500
1> ]
1> M:\mmgit\mmcyb\inc\format.h(425) : see reference to class template instantiation 'fmt::internal::Array<T,SIZE>' being compiled
1> with
1> [
1> T=char,
1> SIZE=500
1> ]
1> M:\mmgit\mmcyb\inc\format.h(872) : see reference to class template instantiation 'fmt::BasicWriter' being compiled
1> with
1> [
1> Char=char
1> ]
1> M:\mmgit\mmcyb\inc\format.h(1128) : see reference to class template instantiation 'fmt::BasicFormatter' being compiled
1> with
1> [
1> Char=char
1> ]
1>M:\mmgit\mmcyb\inc\format.h(106): error C2059: syntax error : '::'
1>M:\mmgit\mmcyb\inc\format.h(106): error C2589: '(' : illegal token on right side of '::'
1> M:\mmgit\mmcyb\inc\format.h(105) : while compiling class template member function 'void fmt::internal::Array<T,SIZE>::Grow(size_t)'
1> with
1> [
1> T=const fmt::BasicFormatter::Arg *,
1> SIZE=10
1> ]
1> M:\mmgit\mmcyb\inc\format.h(979) : see reference to class template instantiation 'fmt::internal::Array<T,SIZE>' being compiled
1> with
1> [
1> T=const fmt::BasicFormatter::Arg *,
1> SIZE=10
1> ]
1>M:\mmgit\mmcyb\inc\format.h(106): error C2059: syntax error : '::'
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.98
64bit build:
1: Converting 14 long long with 10 base-10 digits (no sign) to buffer 300 bytes
1: sizeof(short, int, long, long long): 2 4 8 8
1: Run tests #1 #2 #3 #4 #5 Results:
1: (!) fmt::FormatInt [avg:26419050 var:0.0692767% ms:26 runs:50 conv_ops:49999600]
1: (+183%) boost::spirit::karma [avg:74907132 var:0.162081% ms:74 runs:50 conv_ops:49999600]
32bit build:
1: Converting 14 long long with 10 base-10 digits (no sign) to buffer 300 bytes
1: sizeof(short, int, long, long long): 2 4 4 8
1: Run tests #1 #2 #3 #4 #5 Results:
1: (!) fmt::FormatInt [avg:115024795 var:0.554144% ms:115 runs:50 conv_ops:49999600]
1: (+98%) boost::spirit::karma [avg:228828029 var:0.15578% ms:228 runs:50 conv_ops:49999600]
In some cases boost::karma
works better:
1: Converting 25 int with 4 base-10 digits to buffer 300 bytes
1: sizeof(short, int, long, long long): 2 4 4 8
1: Run tests #1 #2 #3 #4 #5 Results:
1: (+75%) fmt::FormatInt [avg:45775614 var:0.0263464% ms:45 runs:50 conv_ops:50000000]
1: (!) boost::spirit::karma [avg:26063573 var:1.59616% ms:26 runs:50 conv_ops:50000000]
It's probably because every type converting to uint64_t. May be template parameter is more appropriate?
32bit: https://s3.amazonaws.com/archive.travis-ci.org/jobs/19018932/log.txt
64bit: https://s3.amazonaws.com/archive.travis-ci.org/jobs/19018934/log.txt
Current version of FormatInt
class set terminating '\0' character automatically. I think it's better to follow principle don't pay for what you don't use
and let user set '\0' when he really wants it.
This should return 0x61
, but instead fails saying it needs a numeric type instead of a character type.
fmt::format("0x{0:02X}", 'a'); // Crashes
This, however, succeeds:
fmt::format("0x{0:02X}\n", (int)'a'); // Returns 0x61
sprintf_s calls the invalid_parameter_handler function if the buffer size does not fit the input, instead of directly returning the written count.
A fix could be to use instead _vsnprintf_s with _TRUNCATE to get an error return value.
Small test is:
fmt::Writer writer;
int i = 0;
while ( i++ < 130 )
{
std::cout << i << std::endl;
writer << 1.01;
}
This fails with Visual Studio.
VS 2012 (Update 4) doesn't have the initializer_list header and fails to compile because of the FMT_USE_INITIALIZER_LIST test.
There's a workaround for VS2012, but it's still in some alpha stage. I'd suggest changing the minimum version to 1800 (VS 2013).
Support for long long
should be implemented similar to the one for unsigned long long
added in #8 . Both need to be tested.
I'm going to add localization in the project https://github.com/HarpyWar/pvpgn, and I find your library is well suited for this purpose.
Now I use code like this:
fmt::Formatter<> localize(t_connection c, const char *format)
{
// localization stuff here (t_connection is needed to get user language)
...
fmt::Formatter<> f(format);
return f;
}
std::string text = str(localize(c, "Account {} has been muted.") << username);
Is there way to avoid additional str
wrapper? I'm not a good C++ programmer and I just want to make sure that I do it correctly, and there is no a better/shorter way like this:
std::string text = localize(c, "Account {} has been muted.") << username;
or
std::string text = localize(c, "Account {} has been muted.", username);
FormatDec
works incorrectly with short
type:
1: Convert -10 failed for fmt::FormatInt
1: Incorrect algorithm
Is there an example how to use this library? I have downloaded 0.9.0 release, add two files in my vs2013 project solution: format.h
and format.cc
, then #include format.h
in my program.
But I receive a lot of compile errors.
Should I use cmake before or it is not necessary?
Warning 1 warning C4627: '#include "format.h"': skipped when looking for precompiled header use m:\projects\test\format.cс 34 1 test
Warning 2 warning C4603: '_CRT_SECURE_NO_WARNINGS' : macro is not defined or definition is different after precompiled header use m:\projects\test\format.cс 30 1 test
Warning 3 warning C4603: '_SCL_SECURE_NO_WARNINGS' : macro is not defined or definition is different after precompiled header use m:\projects\test\format.cс 32 1 test
Error 4 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 52 1 test
Error 5 error C2873: 'ULongLong' : symbol cannot be used in a using-declaration m:\projects\test\format.cс 52 1 test
Error 6 error C3861: '_ecvt_s': identifier not found m:\projects\test\format.cс 90 1 test
Error 7 error C3861: '_finite': identifier not found m:\projects\test\format.cс 94 1 test
Error 8 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 108 1 test
Error 9 error C2065: 'Writer' : undeclared identifier m:\projects\test\format.cс 108 1 test
Error 10 error C2059: syntax error : ',' m:\projects\test\format.cс 108 1 test
Error 11 error C2065: 'FormatFunc' : undeclared identifier m:\projects\test\format.cс 110 1 test
Error 12 error C2146: syntax error : missing ')' before identifier 'func' m:\projects\test\format.cс 110 1 test
Error 13 error C2182: 'ReportError' : illegal use of type 'void' m:\projects\test\format.cс 110 1 test
Error 14 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 111 1 test
Error 15 error C2059: syntax error : ')' m:\projects\test\format.cс 111 1 test
Error 16 error C2143: syntax error : missing ';' before '{' m:\projects\test\format.cс 111 1 test
Error 17 error C2447: '{' : missing function header (old-style formal list?) m:\projects\test\format.cс 111 1 test
Error 18 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 122 1 test
Error 19 error C2143: syntax error : missing ';' before '<' m:\projects\test\format.cс 122 1 test
Error 20 error C2988: unrecognizable template declaration/definition m:\projects\test\format.cс 122 1 test
Error 21 error C2059: syntax error : '<' m:\projects\test\format.cс 122 1 test
Error 22 error C2039: 'FormatFloat' : is not a member of '`global namespace'' m:\projects\test\format.cс 122 1 test
Error 23 error C2039: 'size_t' : is not a member of 'std' m:\projects\test\format.cс 123 1 test
Error 24 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 136 1 test
Error 25 error C2039: 'FormatFloat' : is not a member of '`global namespace'' m:\projects\test\format.cс 136 1 test
Error 26 error C2039: 'size_t' : is not a member of 'std' m:\projects\test\format.cс 137 1 test
Error 27 error C2143: syntax error : missing ';' before '{' m:\projects\test\format.cс 138 1 test
Error 28 error C2447: '{' : missing function header (old-style formal list?) m:\projects\test\format.cс 138 1 test
Error 29 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 149 1 test
Error 30 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int m:\projects\test\format.cс 167 1 test
Error 31 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 167 1 test
Error 32 error C2146: syntax error : missing ';' before identifier 'POWERS_OF_10_32' m:\projects\test\format.cс 167 1 test
Error 33 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int m:\projects\test\format.cс 168 1 test
Error 34 error C2653: 'fmt' : is not a class or namespace name m:\projects\test\format.cс 168 1 test
Error 35 error C2146: syntax error : missing ';' before identifier 'POWERS_OF_10_64' m:\projects\test\format.cс 168 1 test
Error 36 error C3861: 'ULongLong': identifier not found m:\projects\test\format.cс 171 1 test
Error 37 error C1903: unable to recover from previous error(s); stopping compilation m:\projects\test\format.cс 171 1 test
Start 5: posix-test 5/6 Test #5: posix-test .......................***Failed 0.01 sec Start 6: compile-test 6/6 Test #6: compile-test .....................***Failed 0.00 sec
some compilers (gcc,clang) can check printf like functions
in Os X it works like this
int printf(const char * __restrict, ...) __printflike(1, 2);
int sprintf(char * __restrict, const char * __restrict, ...) __printflike(2, 3);
int sscanf(const char * __restrict, const char * __restrict, ...) __scanflike(2, 3);
int vsprintf(char * __restrict, const char * __restrict, va_list) __printflike(2, 0);
int snprintf(char * __restrict, size_t, const char * __restrict, ...) __printflike(3, 4);
int vsnprintf(char * __restrict, size_t, const char * __restrict, va_list) __printflike(3, 0);
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
i fink it good idea to add something similar to your library
you can take some additional information here https://mail-index.netbsd.org/tech-userlevel/2012/03/04/msg006197.html
The README file is too big. Some of the content needs to be moved to the website and updated.
I've been trying to compile your library with intel c compiler and -std=c++11 flag enabled:
format.cc(55): error: more than one instance of overloaded function "signbit" matches the argument list:
function "signbit(double)"
function "std::signbit(double)"
argument types are: (double)
return signbit(value);
^
compilation aborted for format.cc (code 2)
$ icc -v
$ icc version 14.0.2 (gcc version 4.6.0 compatibility)
with -std=gnu++98 (default) everything is good.
BasicFormatter::Arg has a constructor from a std::string, but not a constructor from a std::wstring; this leads to std::wstring being treated as a custom type.
Arg(const std::string &value) : type(STRING), formatter(0) {
string.value = value.c_str();
string.size = value.size();
}
I'm not sure if the correct solution is to add a second constructor for std::wstring:
Arg(const std::wstring &value) : type(STRING), formatter(0) {
string.value = value.c_str();
string.size = value.size();
}
Or whether to use std::basic_string (which will automatically add the correct type of STL constructor based on the current char type of the formatter):
Arg(const std::basic_string<Char> &value) : type(STRING), formatter(0) {
string.value = value.c_str();
string.size = value.size();
}
However both worked when I tried them.
Currently cppx algorithm works incorrectly when sizeof(long long) != sizeof(long).
Is there any interest in testing cppx?
Failed build: https://travis-ci.org/ruslo/int-dec-format-tests/jobs/18972453
Raw text: https://s3.amazonaws.com/archive.travis-ci.org/jobs/18972453/log.txt
1: Converting 1 long long with ANY base-10 digits to buffer 30 bytes
1: sizeof(short, int, long, long long): 2 4 4 8
1: Convert 9223372036854775807 failed for cppx::decimal_from
1: Incorrect algorithm
Hi,
I've found the speed-test below on another library page where a guy compared "format" (not a unique name btw.) against Boost Karma, among others. And Karma generally was either as fast as format or even faster.
I would love to see how you benchmark this and how you explain this. Thanks in advance.
------------------------------------snip--------------------------------------
Well, README.md
of project https://github.com/vitaut/format
reference to spirit.karma, but I don't have any speed test results, so
I've cloned your project and find only one test called int-generator
.
I've tested it on Visual Studio 2013 x64 compiler with full optimization (/Ox):
cl /c /W3 /WX- /Ox /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D HAVE_BOOST /D "CMAKE_INTDIR="Release"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"format.dir\Release" /Fd"format.dir\Release\vc120.pdb" /Gd /TP /errorReport:prompt ..\format.cc
cl /c /W3 /WX- /Ox /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D HAVE_BOOST /D "CMAKE_INTDIR="Release"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"int-generator.dir\Release" /Fd"int-generator.dir\Release\vc120.pdb" /Gd /TP /errorReport:prompt "....\format-benchmark\int_generator.cpp"
Results (MAX_ITERATION = 1e8):
ltoa: 12.3518 [s]
sprintf: 23.7584 [s]
sprintf+std::string: 25.3529 [s]
std::stringstream: 71.6845 [s]
std::to_string: 28.8839 [s]
boost::lexical_cast: 14.7594 [s]
karma::generate: 4.68553 [s]
karma::generate+std::string: 6.09963 [s]
fmt::Writer: 3.75357 [s]
fmt::Writer+std::string: 6.60581 [s]
fmt::Format: 10.4957 [s]
fmt::Format+std::string: 13.3467 [s]
fmt::FormatInt: 3.61697 [s]
cppx::decimal_from: 3.82345 [s]
As you can see boost libraries lexical_cast and karma are "among the slickest and fastest".
lexical_cast is twice faster then c-style sprintf and STL-style stringstream and to_string
and only ~20% slower then c-style ltoa.
Boost.karma already works better then fmt::*
with std::string:
karma::generate+std::string: 6.09963 [s]
fmt::Writer+std::string: 6.60581 [s]
fmt::Format+std::string: 13.3467 [s]
Boost.karma works about twice faster than fmt::Format
:
karma::generate: 4.68553 [s]
fmt::Format: 10.4957 [s]
FormatInt is not working with int64 type (ostringstream, to_string, boost.karma and boost.lexical_cast works fine).
So only fmt::Writer is rest:
karma::generate: 4.68553 [s]
fmt::Writer: 3.75357 [s]
Let's test it with little numbers. Patched fill function:
struct random_fill {
int operator()() const {
int scale = std::rand() / 100 + 1;
return ((std::rand() \* std::rand()) / scale);
return ((std::rand() \* std::rand()) / scale) % 100;
Voila!
karma::generate: 1.35417 [s]
fmt::Writer: 1.88881 [s]
And modulus 10:
struct random_fill {
int operator()() const {
int scale = std::rand() / 100 + 1;
return ((std::rand() \* std::rand()) / scale) % 10;
return ((std::rand() \* std::rand()) / scale);
Result (karma twice faster!):
karma::generate: 0.855458 [s]
fmt::Writer: 1.61517 [s]
I'm still getting an error here when calling fmt::format("{0:02X}", 'x');
and I think it's because it's not liking the number alignment, but... 'x'
is a number in this case.
// format.cc:444
if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
throw FormatError("invalid format specifier for char");
The stream operator << dosen't work as expected, based on the use being equivalent to std::ostream.
fmt::Formatter<> msg = fmt::Format(format);
msg << arg1;
msg << arg2;
...
msg << argN;
result = fmt::str(msg);
throws exception, to many formatting tokens on the second line, as it immediately attempts to format the string, but not all arguments have been passed.
P.S. I need to use this method as my code is actually
template<typename... Args> inline std::string const & Format(std::string const &format,Args const & ... args) {
fmt::Formatter<> msg = fmt::Format(format);
RescursiveFormat(msg,args...);
return *new std::string(fmt::str(msg)); }
Where RescursiveFormat(msg,args...); reduce to (by template meta programing, and compiler optimization)
msg << arg1;
msg << arg2;
...
msg << argN;
For however may arguments are passed.
This allows formatting to be done by
Format(<format_string>,...) i.e. like sprintf, by type-safe, and using format as the underlining formatting method.
For efficiency, the overload of Format that takes arbitrary number of arguments shouldn't construct std::string. Also there is an unnecessary copying of arguments.
... so build breaks at line 407 of format.h
gcc version 4.8.2 20140120 (ALT Linux 4.8.2-alt3) (GCC)
The fix is trivial, I'll attach it right now
Hello
Is an upgrade using new C++11 features si to be expected ? I believe some parts of the code could be replaced by new standard templates, particularly regarding the traits (IsDouble and things like that).
A compile-time parsing of the format strings using constexpr features could be done, but that is a more tricky part.
// Format using snprintf.
Char fill = static_cast<Char>(spec.fill());
for (;;) {
std::size_t size = buffer_.capacity() - offset;
Char *start = &buffer_[offset];
int n = internal::CharTraits<Char>::FormatFloat(start, size, format, width_for_sprintf, precision, value);
It is possible for size to be equal 0.
As a workaround , I added GrowBuffer(1000) and recalculated size again.
I discovered doing some testing that print() only accepts a C FILE file-pointer, but not an fasteam object. As a C++ lib shouldn't it also offer fstream support?
Prepare packages for downloading the format library including the documentation.
Include (fused) version of gtest in the package to make it possible to run tests.
Clarify in the documentation that '#' used together with 'X' adds prefix "0X" (note uppercase 'X') to the output value. Similarly 'B' specifier that adds prefix '0B' should be added. See also #4
Broken links to fmt::format
and fmt::print
in http://cppformat.github.io/doc/latest/index.html#format-string-syntax.
Currently the C++ Format library uses format string syntax based on Python's str.format. It should be pretty easy to add support for printf's string syntax for legacy code.
Need to come up with a different project name that is easier to distinguish from Boost Format and others.
/home/travis/build/cppformat/format/format.h:91:19: warning: ISO C++ 1998 does not support ‘long long’ [-Wlong-long]
/home/travis/build/cppformat/format/format.h:92:19: warning: ISO C++ 1998 does not support ‘long long’ [-Wlong-long]
Currently there is an inconsistency in function naming. Some functions are named according to Google C++ Style Guide:
Format
Print
Clear
ReportSystemError
Other follow standard library conventions:
c_str
str
clear
resize
reserve
printf
sprintf
The names should be unified before the version 1.0 of the API is released. This is pretty arbitrary, but it's probably better to follow standard library conventions for public API for consistency with printf
and because its done already for most functions.
Provide 2-3 examples of real Windows error codes in the example so its usage makes sense and mention what happens if you enter a code that is not an official error code.
Hi,
Firstly thanks for the library, it will help me produce better error messages!
I am very new to C++ in general so I may be doing something very wrong but after adding the header and the code file I get 47 warnings all of the types:
Warning 1 warning C4521: 'fmt::BasicFormatter' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1015 1 LightBot
Warning 2 warning C4521: 'fmt::Formatter<>' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1138 1 LightBot
Warning 3 warning C4521: 'fmt::BasicFormatter' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1015 1 LightBot
Warning 4 warning C4521: 'fmt::Formatter<Action,Char>' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1138 1 LightBot
I don't believe I am doing something wrong? Additionally is the library cross platform?
Here's how to reproduce:
mkdir build && cd build && cmake -G Xcode ..
Here's the crash report:
Process: util-test [99663]
Path: /Users/USER/Desktop/*/util-test
Identifier: util-test
Version: 0
Code Type: X86-64 (Native)
Parent Process: util-test [99660]
Responsible: Xcode [99349]
User ID: 501
Date/Time: 2014-08-21 08:49:37.471 -0700
OS Version: Mac OS X 10.9.4 (13E28)
Report Version: 11
Anonymous UUID: A313BD1C-E57C-0B66-D31B-15AC4B26A391
Sleep/Wake UUID: 8804A7BB-AD23-4561-B5BC-CE0436895581
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Application Specific Information:
crashed on child side of fork pre-exec
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff8a95d866 __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff93e7235c pthread_kill + 92
2 libsystem_c.dylib 0x00007fff8fb48b1a abort + 125
3 libsystem_c.dylib 0x00007fff8fb1298e __assert_rtn + 272
4 util-test 0x000000010005681f fmt::internal::StrError(int, char*&, unsigned long) + 111 (format.cc:263)
5 util-test 0x00000001000020a4 UtilTest_StrError_Test::TestBody() + 580 (util-test.cc:141)
6 util-test 0x000000010004bf13 void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) + 131 (gtest.cc:2090)
7 util-test 0x0000000100038267 void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) + 119 (gtest.cc:2126)
8 util-test 0x000000010001e475 testing::Test::Run() + 197 (gtest.cc:2161)
9 util-test 0x000000010001f5ab testing::TestInfo::Run() + 219 (gtest.cc:2338)
10 util-test 0x0000000100020387 testing::TestCase::Run() + 231 (gtest.cc:2444)
11 util-test 0x00000001000276ee testing::internal::UnitTestImpl::RunAllTests() + 926 (gtest.cc:4236)
12 util-test 0x0000000100048c53 bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) + 131 (gtest.cc:2090)
13 util-test 0x000000010003a9e7 bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) + 119 (gtest.cc:2126)
14 util-test 0x0000000100027334 testing::UnitTest::Run() + 100 (gtest.cc:3871)
15 util-test 0x0000000100013a33 main + 51 (test-main.cc:43)
16 libdyld.dylib 0x00007fff954985fd start + 1
/format.h: In function 'fmt::Formatter<fmt::NoAction, char> fmt::Format(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = char]' is private
/format.h:1226: error: within this context
/format.h: In function 'fmt::Formatter<fmt::NoAction, wchar_t> fmt::Format(fmt::WStringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = wchar_t]' is private
/format.h:1230: error: within this context
/format.h: In function 'fmt::Formatter<fmt::Write, char> fmt::Print(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::Write, Char = char]' is private
/format.h:1246: error: within this context
In file included from /format.cc:34:
/format.h: In function 'fmt::Formatter<fmt::NoAction, char> fmt::Format(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = char]' is private
/format.h:1226: error: within this context
/format.h: In function 'fmt::Formatter<fmt::NoAction, wchar_t> fmt::Format(fmt::WStringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = wchar_t]' is private
/format.h:1230: error: within this context
/format.h: In function 'fmt::Formatter<fmt::Write, char> fmt::Print(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::Write, Char = char]' is private
/format.h:1246: error: within this context
Hi, thanks for your library! I'm just evaluating it for logging purposes and came across one problem. When trying wide char version of the format string:
auto x = fmt::str(fmt::Format(L"{}") << true);
or
std::wstring xx = fmt::str(fmt::Format(L"{}") << std::wstring(L"wstring"));
I got compile time error (VC2010), complaining that:
void Write(const std::basic_string<char> &s, ...) doesn't accept std::basic_string<wchar_t>
works fine once I changed Write method to this:
template <typename Char>
void Write(const std::basic_string<Char> &s, const FormatSpec &spec) {
FormatString(s.data(), s.size(), spec);
}
The library looks exactly what I was looking for: replacement-based API (without a need to specify type in format string), type-safe, super fast and small.
For logging purposes, however, it would be nice to be able to turn-off exceptions (replaced by debug assert() + "bad format" result?) instead of try/catch the fmt::Format calls. Have you considered header-only version?
Thanks again
Filip Jerabek
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.