constexpr for compiled fmt
This commit is contained in:
parent
f8c9fabd94
commit
eaf8c1b772
@ -135,7 +135,7 @@ struct udl_compiled_string : compiled_string {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, typename... Tail>
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,8 +504,8 @@ FMT_BEGIN_EXPORT
|
|||||||
template <typename CompiledFormat, typename... Args,
|
template <typename CompiledFormat, typename... Args,
|
||||||
typename Char = typename CompiledFormat::char_type,
|
typename Char = typename CompiledFormat::char_type,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||||
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
|
FMT_CONSTEXPR20 FMT_INLINE std::basic_string<Char> format(
|
||||||
const Args&... args) {
|
const CompiledFormat& cf, const Args&... args) {
|
||||||
auto s = std::basic_string<Char>();
|
auto s = std::basic_string<Char>();
|
||||||
cf.format(std::back_inserter(s), args...);
|
cf.format(std::back_inserter(s), args...);
|
||||||
return s;
|
return s;
|
||||||
@ -520,8 +520,8 @@ constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
|||||||
|
|
||||||
template <typename S, typename... Args,
|
template <typename S, typename... Args,
|
||||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
FMT_INLINE FMT_CONSTEXPR20 std::basic_string<typename S::char_type> format(
|
||||||
Args&&... args) {
|
const S&, Args&&... args) {
|
||||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
||||||
constexpr auto str = basic_string_view<typename S::char_type>(S());
|
constexpr auto str = basic_string_view<typename S::char_type>(S());
|
||||||
if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') {
|
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.
|
// Extracts a reference to the container from back_insert_iterator.
|
||||||
template <typename Container>
|
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& {
|
-> Container& {
|
||||||
using base = std::back_insert_iterator<Container>;
|
using base = std::back_insert_iterator<Container>;
|
||||||
struct accessor : base {
|
struct accessor : base {
|
||||||
accessor(base b) : base(b) {}
|
FMT_CONSTEXPR accessor(base b) : base(b) {}
|
||||||
using base::container;
|
using base::container;
|
||||||
};
|
};
|
||||||
return *accessor(it).container;
|
return *accessor(it).container;
|
||||||
@ -933,7 +933,8 @@ template <typename T> class buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Appends data to the end of the 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& {
|
template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
|
||||||
return ptr_[index];
|
return ptr_[index];
|
||||||
@ -1493,8 +1494,8 @@ class appender : public std::back_insert_iterator<detail::buffer<char>> {
|
|||||||
appender(base it) noexcept : base(it) {}
|
appender(base it) noexcept : base(it) {}
|
||||||
FMT_UNCHECKED_ITERATOR(appender);
|
FMT_UNCHECKED_ITERATOR(appender);
|
||||||
|
|
||||||
auto operator++() noexcept -> appender& { return *this; }
|
FMT_CONSTEXPR20 auto operator++() noexcept -> appender& { return *this; }
|
||||||
auto operator++(int) noexcept -> appender { return *this; }
|
FMT_CONSTEXPR20 auto operator++(int) noexcept -> appender { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// A formatting argument. It is a trivially copyable/constructible type to
|
// 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 {
|
namespace detail {
|
||||||
|
|
||||||
template <typename Char, typename InputIt>
|
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);
|
get_container(out).append(begin, end);
|
||||||
return out;
|
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.
|
// A workaround for std::string not having mutable data() until C++17.
|
||||||
template <typename Char>
|
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];
|
return &s[0];
|
||||||
}
|
}
|
||||||
template <typename Container>
|
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();
|
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
|
#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
|
||||||
__attribute__((no_sanitize("undefined")))
|
__attribute__((no_sanitize("undefined")))
|
||||||
#endif
|
#endif
|
||||||
inline auto
|
inline FMT_CONSTEXPR auto
|
||||||
reserve(std::back_insert_iterator<Container> it, size_t n)
|
reserve(std::back_insert_iterator<Container> it, size_t n)
|
||||||
-> checked_ptr<typename Container::value_type> {
|
-> checked_ptr<typename Container::value_type> {
|
||||||
Container& c = get_container(it);
|
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)>
|
template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
|
||||||
inline auto base_iterator(std::back_insert_iterator<Container>& it,
|
inline FMT_CONSTEXPR auto base_iterator(
|
||||||
checked_ptr<typename Container::value_type>)
|
std::back_insert_iterator<Container>& it,
|
||||||
|
checked_ptr<typename Container::value_type>)
|
||||||
-> std::back_insert_iterator<Container> {
|
-> std::back_insert_iterator<Container> {
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
@ -875,13 +877,14 @@ using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename U>
|
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) {
|
while (begin != end) {
|
||||||
auto count = to_unsigned(end - begin);
|
auto count = to_unsigned(end - begin);
|
||||||
try_reserve(size_ + count);
|
try_reserve(size_ + count);
|
||||||
auto free_cap = capacity_ - size_;
|
auto free_cap = capacity_ - size_;
|
||||||
if (free_cap < count) count = free_cap;
|
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;
|
size_ += count;
|
||||||
begin += count;
|
begin += count;
|
||||||
}
|
}
|
||||||
@ -4462,14 +4465,15 @@ auto join(Range&& range, string_view sep)
|
|||||||
\endrst
|
\endrst
|
||||||
*/
|
*/
|
||||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
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();
|
auto buffer = memory_buffer();
|
||||||
detail::write<char>(appender(buffer), value);
|
detail::write<char>(appender(buffer), value);
|
||||||
return {buffer.data(), buffer.size()};
|
return {buffer.data(), buffer.size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
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
|
// The buffer should be large enough to store the number including the sign
|
||||||
// or "false" for bool.
|
// or "false" for bool.
|
||||||
constexpr int max_size = detail::digits10<T>() + 2;
|
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("false", test_format<6>(FMT_COMPILE("{}"), false));
|
||||||
EXPECT_EQ("true ", test_format<6>(FMT_COMPILE("{:5}"), true));
|
EXPECT_EQ("true ", test_format<6>(FMT_COMPILE("{:5}"), true));
|
||||||
EXPECT_EQ("1", test_format<2>(FMT_COMPILE("{:d}"), 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) {
|
TEST(compile_time_formatting_test, integer) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user