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
Issues with compiled format #1324
Comments
Thanks for reporting. The |
Removing |
The compiled format already contains formatting argument types but doesn't enforce compatibility yet.
Yes, support for user-defined types is not implemented in |
Thanks for the clarification. Any ideas if or when custom types will be supported in Lines 22 to 25 in 4b8f8fa
with
My guess is that compile time enforcement wouldn't work with dynamic specs but at least it should be enforced at runtime. |
It will be supported eventually but I don't have any specific dates.
Conceptually yes except that we cannot use
Yes. |
This should fixed now and all the examples here work as expected using the new #include <fmt/compile.h>
#include <fmt/format.h>
#include <iostream>
struct formattable {
int i;
};
FMT_BEGIN_NAMESPACE
template <> struct formatter<formattable> : formatter<int> {
bool special{false};
template <typename ParseContext>
constexpr auto parse(ParseContext &ctx) -> decltype(ctx.begin()) {
if (*(ctx.begin()) == '!') {
special = true;
ctx.advance_to(ctx.begin() + 1);
if (*(ctx.begin()) == 'N')
ctx.advance_to(ctx.begin() + 1);
}
return formatter<int>::parse(ctx);
}
template <typename FormatContext>
auto format(formattable f, FormatContext &ctx) -> decltype(ctx.out()) {
if (special)
ctx.out() = '~';
return formatter<int>::format(f.i, ctx);
}
};
FMT_END_NAMESPACE
int main() {
// prints "00002" as expected
std::cout << fmt::format(FMT_STRING("{:05}\n"), formattable{2});
// prints "~2" as expected
std::cout << fmt::format(FMT_STRING("{:!}\n"), formattable{2});
// prints "2-42"
std::cout << fmt::format(FMT_COMPILE("{}-{}\n"), formattable{2}, formattable{42});
// prints "2"
std::cout << fmt::format(FMT_COMPILE("{}\n"), formattable{2});
// prints "~2"
std::cout << fmt::format(FMT_COMPILE("{:!}\n"), formattable{2});
// Fails to compile because of incorrect specifier.
// std::cout << fmt::format(FMT_COMPILE("{:!}\n"), 5.3);
// prints "~42"
std::cout << fmt::format(FMT_COMPILE("{:!N}\n"), formattable{42});
} Code generation for user-defined types is suboptimal but it will be addressed separately. |
I've been trying out compiling format strings and run into a few issues when using custom types with examples at the end (I know it's still experimental):
get
function fails to compile when using multiple type arguments infmt::compile
fmt/include/fmt/compile.h
Lines 332 to 339 in 758446c
It should look like:
In header-only mode:
fmt/include/fmt/compile.h
Line 416 in 758446c
clashes with
fmt/include/fmt/format-inl.h
Line 553 in 758446c
Type safety can be violated quite easily:
Maybe the compiled format should contain template arguments that could later be used to enforce type safety at compile time but still allowing implicit conversions?
crashes at runtime with
Stack:
std::cout << fmt::format(FMT_STRING("{:!}\n"), 5.3);
fails to compile whileconstexpr auto f4 = fmt::compile<double>(FMT_STRING("{:!}\n"));
compiles fine.std::cout << fmt::format(f4, 42.0);
crashes at runtime with:Stack:
This is from
fmt/include/fmt/compile.h
Lines 225 to 226 in 758446c
arg_formatter
tries to dereferencenullptr
. Stack:fmt::format
or similar:Compiler output:
Example source file compiled with GCC 9.2 C++17:
The text was updated successfully, but these errors were encountered: