constexpr for compiled fmt
This commit is contained in:
parent
f8c9fabd94
commit
eaf8c1b772
@ -135,7 +135,7 @@ struct udl_compiled_string : compiled_string {
|
||||
#endif
|
||||
|
||||
template <typename T, typename... Tail>
|
||||
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 <typename CompiledFormat, typename... Args,
|
||||
typename Char = typename CompiledFormat::char_type,
|
||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
FMT_CONSTEXPR20 FMT_INLINE std::basic_string<Char> format(
|
||||
const CompiledFormat& cf, const Args&... args) {
|
||||
auto s = std::basic_string<Char>();
|
||||
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 <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||
Args&&... args) {
|
||||
FMT_INLINE FMT_CONSTEXPR20 std::basic_string<typename S::char_type> format(
|
||||
const S&, Args&&... args) {
|
||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
||||
constexpr auto str = basic_string_view<typename S::char_type>(S());
|
||||
if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') {
|
||||
|
||||
@ -825,11 +825,11 @@ constexpr auto has_const_formatter() -> bool {
|
||||
|
||||
// Extracts a reference to the container from back_insert_iterator.
|
||||
template <typename Container>
|
||||
inline auto get_container(std::back_insert_iterator<Container> it)
|
||||
FMT_CONSTEXPR inline auto get_container(std::back_insert_iterator<Container> it)
|
||||
-> Container& {
|
||||
using base = std::back_insert_iterator<Container>;
|
||||
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 <typename T> class buffer {
|
||||
}
|
||||
|
||||
/** Appends data to the end of the buffer. */
|
||||
template <typename U> void append(const U* begin, const U* end);
|
||||
template <typename U>
|
||||
void FMT_CONSTEXPR append(const U* begin, const U* end);
|
||||
|
||||
template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
|
||||
return ptr_[index];
|
||||
@ -1493,8 +1494,8 @@ class appender : public std::back_insert_iterator<detail::buffer<char>> {
|
||||
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 <typename Char, typename InputIt>
|
||||
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;
|
||||
}
|
||||
|
||||
@ -546,11 +546,12 @@ template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
|
||||
|
||||
// A workaround for std::string not having mutable data() until C++17.
|
||||
template <typename Char>
|
||||
inline auto get_data(std::basic_string<Char>& s) -> Char* {
|
||||
inline FMT_CONSTEXPR auto get_data(std::basic_string<Char>& s) -> Char* {
|
||||
return &s[0];
|
||||
}
|
||||
template <typename Container>
|
||||
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 <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::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<Container> it, size_t n)
|
||||
-> checked_ptr<typename Container::value_type> {
|
||||
Container& c = get_container(it);
|
||||
@ -612,8 +613,9 @@ template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
|
||||
}
|
||||
|
||||
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
||||
inline auto base_iterator(std::back_insert_iterator<Container>& it,
|
||||
checked_ptr<typename Container::value_type>)
|
||||
inline FMT_CONSTEXPR auto base_iterator(
|
||||
std::back_insert_iterator<Container>& it,
|
||||
checked_ptr<typename Container::value_type>)
|
||||
-> std::back_insert_iterator<Container> {
|
||||
return it;
|
||||
}
|
||||
@ -875,13 +877,14 @@ using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
|
||||
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
void buffer<T>::append(const U* begin, const U* end) {
|
||||
FMT_CONSTEXPR void buffer<T>::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 <typename T, FMT_ENABLE_IF(!std::is_integral<T>::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<char>(appender(buffer), value);
|
||||
return {buffer.data(), buffer.size()};
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::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<T>() + 2;
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user