-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Runtime exception instead of compile time error when formatting a user type. #201
Comments
Does |
I depends what kind of conversion operator you mean. I think it provides a conversion to const char*. The throw is on line 436 of format.cc (the first throw in this func);
This is the call stack I get:
|
The value of 'code' is: 115 's' |
#include "format.h"
struct S {};
int main() {
fmt::printf("%s", S());
} gives
So I guess ATL::CAtlString s("hi");
auto formattedString = fmt::format("Hello {}", s); |
formattedString ends up with: "Hello 059E8800" I am working with many old log statements that I wanted to add some type safety to, so I need to stick with the old printf style format strings. I have tried boost::format and that seems to work ok and gives me a compiler error, but I was hoping to avoid the bloat and compile slowness that boost::format brings by using cppformat instead. |
When using fmt::format("Hello {}", s), as you suggest, the debugger ends up in the format function of format.h at line 2246:
On the Here's the stack up to calling the conversion operator:
|
I see that fmt::format(L"Hello {}", s) Printing a pointer instead of a string when mixing wide and narrow strings is a known issue with IOStreams: #include <iostream>
int main() {
std::cout << L"test"; // prints a pointer, e.g. 0x400844
} I'll look if I can add a compile-time error when formatting objects with |
@ScottLangham Thinking more of it, I came to a conclusion that there is no reason for
although I haven't tested this with |
Here's the commit that implements this: 79d8f59 |
Closing for now, but feel free to reopen if there are any issues with this. |
Hi Victor, thanks for your help so far. I've been unable to get to this for a few days. I've tried your latest and it formats ok using char based strings, but I'm using Windows and need wide strings to work. So, I added this after including format.h:
Then, I try this unit test:
But, I still get a pointer value instead of Looking at the commit you made, I notice that you have: Thanks, |
No, it shouldn't for wide strings (it wasn't triggered before because there was no wide string I'm not sure why formatting of |
Scott, vitaut:
Although in both cases, the conversion operator is executed, the first case picks up the inserter for const void*, but the second picks up the desired overload. I don't know if there's a decent solution for c++format, possibly providing an optional |
Thanks, @mwinterb.
I don't think that C++ Format should try providing a workaround for this issue because this is an obvious misuse of implicit conversion (I guess the implications were not fully understood or ignored at the time of ATL design) and because, as you correctly pointed out,
This is probably the best solution. To be more specific, adding something like std::wostream &operator<<(std::wostream &os, const ATL::CAtlStringW &s) {
return os << static_cast<const wchar_t*>(s);
} should do the trick. |
I tried to format a CAtlString (from header atlstr).
I'm using Visual Studio 2013 update 5.
With the following code, I expected that if cppformat isn't aware of CAtlString, I'd get a compile-time error and have to provide an override or template specialization to explain to cppformat what to do. But, I get a run time exception instead.
Am I doing something wrong? This feels a bit error prone as it would be easy to code this by mistake.
The text was updated successfully, but these errors were encountered: