diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 94e13c02..aa91745b 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -135,7 +135,7 @@ struct udl_compiled_string : compiled_string { #endif template -const T& first(const T& value, const Tail&...) { +FMT_CONSTEXPR const T& first(const T& value, const Tail&...) { return value; } @@ -504,8 +504,8 @@ FMT_BEGIN_EXPORT template ::value)> -FMT_INLINE std::basic_string format(const CompiledFormat& cf, - const Args&... args) { +FMT_CONSTEXPR20 FMT_INLINE std::basic_string format( + const CompiledFormat& cf, const Args&... args) { auto s = std::basic_string(); cf.format(std::back_inserter(s), args...); return s; @@ -520,8 +520,8 @@ constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, template ::value)> -FMT_INLINE std::basic_string format(const S&, - Args&&... args) { +FMT_INLINE FMT_CONSTEXPR20 std::basic_string format( + const S&, Args&&... args) { if constexpr (std::is_same::value) { constexpr auto str = basic_string_view(S()); if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { diff --git a/include/fmt/core.h b/include/fmt/core.h index 7cc60924..735c30fc 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -825,11 +825,11 @@ constexpr auto has_const_formatter() -> bool { // Extracts a reference to the container from back_insert_iterator. template -inline auto get_container(std::back_insert_iterator it) +FMT_CONSTEXPR inline auto get_container(std::back_insert_iterator it) -> Container& { using base = std::back_insert_iterator; struct accessor : base { - accessor(base b) : base(b) {} + FMT_CONSTEXPR accessor(base b) : base(b) {} using base::container; }; return *accessor(it).container; @@ -933,7 +933,8 @@ template class buffer { } /** Appends data to the end of the buffer. */ - template void append(const U* begin, const U* end); + template + void FMT_CONSTEXPR append(const U* begin, const U* end); template FMT_CONSTEXPR auto operator[](Idx index) -> T& { return ptr_[index]; @@ -1493,8 +1494,8 @@ class appender : public std::back_insert_iterator> { appender(base it) noexcept : base(it) {} FMT_UNCHECKED_ITERATOR(appender); - auto operator++() noexcept -> appender& { return *this; } - auto operator++(int) noexcept -> appender { return *this; } + FMT_CONSTEXPR20 auto operator++() noexcept -> appender& { return *this; } + FMT_CONSTEXPR20 auto operator++(int) noexcept -> appender { return *this; } }; // A formatting argument. It is a trivially copyable/constructible type to @@ -1604,7 +1605,8 @@ FMT_CONSTEXPR FMT_INLINE auto visit_format_arg( namespace detail { template -auto copy_str(InputIt begin, InputIt end, appender out) -> appender { +FMT_CONSTEXPR20 auto copy_str(InputIt begin, InputIt end, appender out) + -> appender { get_container(out).append(begin, end); return out; } diff --git a/include/fmt/format.h b/include/fmt/format.h index 87b67948..3458d478 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -546,11 +546,12 @@ template using sentinel_t = decltype(std::end(std::declval())); // A workaround for std::string not having mutable data() until C++17. template -inline auto get_data(std::basic_string& s) -> Char* { +inline FMT_CONSTEXPR auto get_data(std::basic_string& s) -> Char* { return &s[0]; } template -inline auto get_data(Container& c) -> typename Container::value_type* { +inline FMT_CONSTEXPR auto get_data(Container& c) -> + typename Container::value_type* { return c.data(); } @@ -574,7 +575,7 @@ template ::value)> #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION __attribute__((no_sanitize("undefined"))) #endif -inline auto +inline FMT_CONSTEXPR auto reserve(std::back_insert_iterator it, size_t n) -> checked_ptr { Container& c = get_container(it); @@ -612,8 +613,9 @@ template auto to_pointer(buffer_appender it, size_t n) -> T* { } template ::value)> -inline auto base_iterator(std::back_insert_iterator& it, - checked_ptr) +inline FMT_CONSTEXPR auto base_iterator( + std::back_insert_iterator& it, + checked_ptr) -> std::back_insert_iterator { return it; } @@ -875,13 +877,14 @@ using is_double_double = bool_constant::digits == 106>; template template -void buffer::append(const U* begin, const U* end) { +FMT_CONSTEXPR void buffer::append(const U* begin, const U* end) { while (begin != end) { auto count = to_unsigned(end - begin); try_reserve(size_ + count); auto free_cap = capacity_ - size_; if (free_cap < count) count = free_cap; - std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count)); + auto out = make_checked(ptr_ + size_, count); + for (size_t i = 0; i < count; ++i) *out++ = begin[i]; size_ += count; begin += count; } @@ -4462,14 +4465,15 @@ auto join(Range&& range, string_view sep) \endrst */ template ::value)> -inline auto to_string(const T& value) -> std::string { +FMT_NODISCARD FMT_CONSTEXPR20 inline auto to_string(const T& value) + -> std::string { auto buffer = memory_buffer(); detail::write(appender(buffer), value); return {buffer.data(), buffer.size()}; } template ::value)> -FMT_NODISCARD inline auto to_string(T value) -> std::string { +FMT_NODISCARD FMT_CONSTEXPR20 inline auto to_string(T value) -> std::string { // The buffer should be large enough to store the number including the sign // or "false" for bool. constexpr int max_size = detail::digits10() + 2; diff --git a/test/compile-test.cc b/test/compile-test.cc index 5c868b84..43916800 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -327,6 +327,10 @@ TEST(compile_time_formatting_test, bool) { EXPECT_EQ("false", test_format<6>(FMT_COMPILE("{}"), false)); EXPECT_EQ("true ", test_format<6>(FMT_COMPILE("{:5}"), true)); EXPECT_EQ("1", test_format<2>(FMT_COMPILE("{:d}"), true)); + static_assert(fmt::format(FMT_COMPILE("{}"), true) == "true"); + static_assert(fmt::format(FMT_COMPILE("{}"), false) == "false"); + static_assert(fmt::format(FMT_COMPILE("{:5}"), true) == "true "); + static_assert(fmt::format(FMT_COMPILE("{:d}"), true) == "1"); } TEST(compile_time_formatting_test, integer) {