-
Hello Quillers,
that is just like what Quill needs, apart from the namespace, that is "fmt" and not "fmtquill". It would be tedious to write a new template specialisation for every such class just because of the namespace change, so I tried this:
But it does not work. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 2 replies
-
Hey! Unfortunately, you need to define the specializations explicitly. As far as I know, C++ doesn't allow defining a generic specialization since the primary template isn't accessible. You can derive from I've put together an example showcasing a few different possibilities. Hope it helps |
Beta Was this translation helpful? Give feedback.
-
I'm kind of in the same boat here. Or, what is different in the quill formatters/codecs that makes them incompatible with existing fmt::formatters? thanks in advance. |
Beta Was this translation helpful? Give feedback.
-
Thank you, @odygrd, hi Ray! I do not care much about the libfmt version, but having two copies in different namespaces seems redundant and makes the migration cumbersome. TLDR; it did not go smoothly, either. I made a few wrapper headers for fmt, e.g. "fmt/format.h" looks like this:
Unfortunately, because of the namespace declaration, I could not define the formatters in the
became:
And also had to define a Codec or wrap the argument into a IMO, a fallback to the "slow path" formatting of custom types and allowing either using an external Fmt (does not need to be backward compatible with ancient versions of Fmt) or if not, at least exposing the internal Fmt (by a macro and having headers in the usual place), would help people migrating to Quill. |
Beta Was this translation helpful? Give feedback.
-
Thanks for giving an insight into the complexity of all this! I saw it was supported before 4.0. Maybe the best would be to get some of the required changes into the upstream, e.g. the protected member issue looks simple, I'm sure PR would be welcome, even if it is not re-using fmt as a dependency, at least the codebases converge. There are too many custom types that I would need to write codecs for, most of which are non-trivially copiable, so I could not make a macro for it. So, I passed This is what I finally came up with:
With this, I can now make the template specialisations for my custom types:
Clearly, this is not as efficient as a "hot path" codec would be, but it compiles and it is functional. I think that Quill should fall back to a codec like this if fmt is able to convert the object to a string (e.g. the stream operator is defined). |
Beta Was this translation helpful? Give feedback.
-
Thanks for the detailed explanation and the code! I replaced my codec with your one. I think it would help others if it was part of the project. Whether there is a fallback to it or not, is secondary. (((I think, it helps at the first encountering with the library when things work out of the box, writing a custom codec is an important optimisation, but not making it should not break the build. But up to you, of course. :-) ))) There is also a https://en.cppreference.com/w/cpp/concepts/convertible_to So, there could be two types, I have the very same problem at a different part of the project, not logging, but collecting data into a file, and the data needs to be converted before writing. This now happens in the producer thread, and when I tried to move it to the consumer thread, it crashed because enqueued data has been destructed in the meantime. Taking a binary copy is one way of dealing with this, but what I thought instead, would be to flush the data queue before the life of the enqueued data is over. That would be even faster, as the data would not need to be copied at all. In my very specific scenario this should work, but maybe a generic solution in Quill would do too many flushes. I thought to mention it, though. My other thought is reflection, that will come with C++26, but most compilers support much of it already, just it needs to be enabled by a flag. |
Beta Was this translation helpful? Give feedback.
-
Hey, Support for logging user-defined types has been improved—thanks for the motivation! You can check out v8.2.0 here: I decided not to offer That said, template <>
struct fmtquill::formatter<UserType> : fmtquill::ostream_formatter {}; I’m not sure when the next release will be, but main branch is always ready to use. |
Beta Was this translation helpful? Give feedback.
Hey!
Unfortunately, you need to define the specializations explicitly. As far as I know, C++ doesn't allow defining a generic specialization since the primary template isn't accessible.
You can derive from
fmt::formatter
, but you'll need to template bothparse
andformat
so they work with differentContext
types. However, if you're deriving fromostream_formatter
, this approach won't work sinceparse
isn't templated.I've put together an example showcasing a few different possibilities. Hope it helps
https://godbolt.org/z/5Wsf5WY6P