Skip to content

Enable constexpr support for fmt::format (fmtlib#3403) #4456

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

msvetkin
Copy link

This PR allows to use fmt::format at compile-time by:

  • Adding FMT_CONSTEXPR_STRING macro
  • Mark format/to_string with FMT_CONSTEXPR_STRING
  • Add a few fmt::format compile-time test-cases

Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

@@ -141,6 +141,33 @@
# define FMT_CONSTEXPR20
#endif

// Detect constexpr std::string.
#if !FMT_USE_CONSTEVAL
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it depend on consteval?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FMT_USE_CONSTEVAL enables FMT_CONSTEXPR20 which is required.
I could add comment or introduce something FMT_USE_CONSTEXPR20

Comment on lines 429 to 431
constexpr auto result = []() {
return fmt::format(FMT_COMPILE("{}"), true) == "true";
}();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a lambda here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, unfortunately we do need it. The issue is that all allocated memory at compile time should be deallocated.
That means we are not able to write like this:

constexpr auto s = fmt::format(FMT_COMPILE("{}"), true)); // leaks allocated memory at compile-time to runtime.
EXPECT_EQ("true", s);

Alternatively we could use static_assert:

static_assert(fmt::format(FMT_COMPILE("{}"), true) == "true");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep the lambda for now but I don't think we need to test different arguments since this is already tested elsewhere. What we need to test here is that fmt::format can be called at compile time so I suggest picking on type of an argument (e.g. int) and testing it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have replaced boolean test cases with int and drop test case for a type with user provided formatter.

@msvetkin msvetkin force-pushed the msvetkin/feat/enable-constexpr-for-format branch from 0363675 to 8468cc5 Compare May 27, 2025 19:41
# define FMT_USE_CONSTEXPR_STRING 0
#elif !defined(__cpp_lib_constexpr_string)
# define FMT_USE_CONSTEXPR_STRING 0
#elif defined(__cpp_lib_constexpr_string) && \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defined(__cpp_lib_constexpr_string) seems redundant since we only enter this branch if !defined(__cpp_lib_constexpr_string) is false.

@msvetkin msvetkin force-pushed the msvetkin/feat/enable-constexpr-for-format branch from 8468cc5 to 6a0595d Compare June 2, 2025 20:53
@msvetkin msvetkin force-pushed the msvetkin/feat/enable-constexpr-for-format branch from 6a0595d to 7e7a4e9 Compare June 4, 2025 19:45
@msvetkin msvetkin requested review from phprus and vitaut June 4, 2025 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants