146
146
// Use the provided definition.
147
147
#elif defined(__GNUC__) && !defined(__EXCEPTIONS)
148
148
# define FMT_USE_EXCEPTIONS 0
149
+ #elif defined(__clang__) && !defined(__cpp_exceptions)
150
+ # define FMT_USE_EXCEPTIONS 0
149
151
#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS
150
152
# define FMT_USE_EXCEPTIONS 0
151
153
#else
@@ -332,6 +334,13 @@ struct monostate {
332
334
# define FMT_ENABLE_IF (...) fmt::enable_if_t <(__VA_ARGS__), int > = 0
333
335
#endif
334
336
337
+ template <typename T> constexpr auto min_of (T a, T b) -> T {
338
+ return a < b ? a : b;
339
+ }
340
+ template <typename T> constexpr auto max_of (T a, T b) -> T {
341
+ return a > b ? a : b;
342
+ }
343
+
335
344
namespace detail {
336
345
// Suppresses "unused variable" warnings with the method described in
337
346
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
@@ -394,7 +403,7 @@ inline auto map(uint128_opt) -> monostate { return {}; }
394
403
#endif
395
404
396
405
#ifndef FMT_USE_BITINT
397
- # define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1400 )
406
+ # define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500 )
398
407
#endif
399
408
400
409
#if FMT_USE_BITINT
@@ -562,8 +571,8 @@ template <typename Char> class basic_string_view {
562
571
563
572
// Lexicographically compare this string reference to other.
564
573
FMT_CONSTEXPR auto compare (basic_string_view other) const -> int {
565
- size_t str_size = size_ < other. size_ ? size_ : other. size_ ;
566
- int result = detail::compare (data_, other.data_ , str_size );
574
+ int result =
575
+ detail::compare (data_, other.data_ , min_of (size_, other. size_ ) );
567
576
if (result != 0 ) return result;
568
577
return size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1 );
569
578
}
@@ -714,7 +723,7 @@ class basic_specs {
714
723
max_fill_size = 4
715
724
};
716
725
717
- unsigned long data_ = 1 << fill_size_shift;
726
+ size_t data_ = 1 << fill_size_shift;
718
727
719
728
// Character (code unit) type is erased to prevent template bloat.
720
729
char fill_data_[max_fill_size] = {' ' };
@@ -793,7 +802,8 @@ class basic_specs {
793
802
template <typename Char> constexpr auto fill_unit () const -> Char {
794
803
using uchar = unsigned char ;
795
804
return static_cast <Char>(static_cast <uchar>(fill_data_[0 ]) |
796
- (static_cast <uchar>(fill_data_[1 ]) << 8 ));
805
+ (static_cast <uchar>(fill_data_[1 ]) << 8 ) |
806
+ (static_cast <uchar>(fill_data_[2 ]) << 16 ));
797
807
}
798
808
799
809
FMT_CONSTEXPR void set_fill (char c) {
@@ -809,6 +819,7 @@ class basic_specs {
809
819
unsigned uchar = static_cast <detail::unsigned_char<Char>>(s[0 ]);
810
820
fill_data_[0 ] = static_cast <char >(uchar);
811
821
fill_data_[1 ] = static_cast <char >(uchar >> 8 );
822
+ fill_data_[2 ] = static_cast <char >(uchar >> 16 );
812
823
return ;
813
824
}
814
825
FMT_ASSERT (size <= max_fill_size, " invalid fill" );
@@ -1627,12 +1638,12 @@ template <typename... T> struct arg_pack {};
1627
1638
template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES>
1628
1639
class format_string_checker {
1629
1640
private:
1630
- type types_[NUM_ARGS > 0 ? NUM_ARGS : 1 ];
1631
- named_arg_info<Char> named_args_[NUM_NAMED_ARGS > 0 ? NUM_NAMED_ARGS : 1 ];
1641
+ type types_[max_of( 1 , NUM_ARGS) ];
1642
+ named_arg_info<Char> named_args_[max_of( 1 , NUM_NAMED_ARGS) ];
1632
1643
compile_parse_context<Char> context_;
1633
1644
1634
1645
using parse_func = auto (*)(parse_context<Char>&) -> const Char*;
1635
- parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1 ];
1646
+ parse_func parse_funcs_[max_of( 1 , NUM_ARGS) ];
1636
1647
1637
1648
public:
1638
1649
template <typename ... T>
@@ -1694,7 +1705,7 @@ template <typename T> class buffer {
1694
1705
protected:
1695
1706
// Don't initialize ptr_ since it is not accessed to save a few cycles.
1696
1707
FMT_MSC_WARNING (suppress : 26495 )
1697
- FMT_CONSTEXPR20 buffer (grow_fun grow, size_t sz) noexcept
1708
+ FMT_CONSTEXPR buffer (grow_fun grow, size_t sz) noexcept
1698
1709
: size_(sz), capacity_(sz), grow_(grow) {}
1699
1710
1700
1711
constexpr buffer (grow_fun grow, T* p = nullptr , size_t sz = 0 ,
@@ -1740,7 +1751,7 @@ template <typename T> class buffer {
1740
1751
// the new elements may not be initialized.
1741
1752
FMT_CONSTEXPR void try_resize (size_t count) {
1742
1753
try_reserve (count);
1743
- size_ = count <= capacity_ ? count : capacity_ ;
1754
+ size_ = min_of ( count, capacity_) ;
1744
1755
}
1745
1756
1746
1757
// Tries increasing the buffer capacity to `new_capacity`. It can increase the
@@ -1788,9 +1799,9 @@ template <typename T> class buffer {
1788
1799
};
1789
1800
1790
1801
struct buffer_traits {
1791
- explicit buffer_traits (size_t ) {}
1792
- auto count () const -> size_t { return 0 ; }
1793
- auto limit (size_t size) -> size_t { return size; }
1802
+ constexpr explicit buffer_traits (size_t ) {}
1803
+ constexpr auto count () const -> size_t { return 0 ; }
1804
+ constexpr auto limit (size_t size) const -> size_t { return size; }
1794
1805
};
1795
1806
1796
1807
class fixed_buffer_traits {
@@ -1799,12 +1810,12 @@ class fixed_buffer_traits {
1799
1810
size_t limit_;
1800
1811
1801
1812
public:
1802
- explicit fixed_buffer_traits (size_t limit) : limit_(limit) {}
1803
- auto count () const -> size_t { return count_; }
1804
- auto limit (size_t size) -> size_t {
1813
+ constexpr explicit fixed_buffer_traits (size_t limit) : limit_(limit) {}
1814
+ constexpr auto count () const -> size_t { return count_; }
1815
+ FMT_CONSTEXPR auto limit (size_t size) -> size_t {
1805
1816
size_t n = limit_ > count_ ? limit_ - count_ : 0 ;
1806
1817
count_ += size;
1807
- return size < n ? size : n ;
1818
+ return min_of ( size, n) ;
1808
1819
}
1809
1820
};
1810
1821
@@ -1962,15 +1973,37 @@ template <typename T = char> class counting_buffer : public buffer<T> {
1962
1973
template <typename T>
1963
1974
struct is_back_insert_iterator <basic_appender<T>> : std::true_type {};
1964
1975
1976
+ template <typename OutputIt, typename InputIt, typename = void >
1977
+ struct has_back_insert_iterator_container_append : std::false_type {};
1978
+ template <typename OutputIt, typename InputIt>
1979
+ struct has_back_insert_iterator_container_append <
1980
+ OutputIt, InputIt,
1981
+ void_t <decltype(get_container(std::declval<OutputIt>())
1982
+ .append(std::declval<InputIt>(),
1983
+ std::declval<InputIt>()))>> : std::true_type {};
1984
+
1965
1985
// An optimized version of std::copy with the output value type (T).
1966
1986
template <typename T, typename InputIt, typename OutputIt,
1967
- FMT_ENABLE_IF (is_back_insert_iterator<OutputIt>::value)>
1987
+ FMT_ENABLE_IF (is_back_insert_iterator<OutputIt>::value&&
1988
+ has_back_insert_iterator_container_append<
1989
+ OutputIt, InputIt>::value)>
1968
1990
FMT_CONSTEXPR20 auto copy (InputIt begin, InputIt end, OutputIt out)
1969
1991
-> OutputIt {
1970
1992
get_container (out).append (begin, end);
1971
1993
return out;
1972
1994
}
1973
1995
1996
+ template <typename T, typename InputIt, typename OutputIt,
1997
+ FMT_ENABLE_IF (is_back_insert_iterator<OutputIt>::value &&
1998
+ !has_back_insert_iterator_container_append<
1999
+ OutputIt, InputIt>::value)>
2000
+ FMT_CONSTEXPR20 auto copy (InputIt begin, InputIt end, OutputIt out)
2001
+ -> OutputIt {
2002
+ auto & c = get_container (out);
2003
+ c.insert (c.end (), begin, end);
2004
+ return out;
2005
+ }
2006
+
1974
2007
template <typename T, typename InputIt, typename OutputIt,
1975
2008
FMT_ENABLE_IF (!is_back_insert_iterator<OutputIt>::value)>
1976
2009
FMT_CONSTEXPR auto copy (InputIt begin, InputIt end, OutputIt out) -> OutputIt {
@@ -2146,7 +2179,8 @@ template <typename Context> class value {
2146
2179
template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
2147
2180
value (const T& named_arg) : value(named_arg.value) {}
2148
2181
2149
- template <typename T, FMT_ENABLE_IF(use_formatter<T>::value)>
2182
+ template <typename T,
2183
+ FMT_ENABLE_IF (use_formatter<T>::value || !FMT_BUILTIN_TYPES)>
2150
2184
FMT_CONSTEXPR20 FMT_INLINE value (T& x) : value(x, custom_tag()) {}
2151
2185
2152
2186
FMT_ALWAYS_INLINE value (const named_arg_info<char_type>* args, size_t size)
@@ -2220,9 +2254,12 @@ struct locale_ref {
2220
2254
2221
2255
public:
2222
2256
constexpr locale_ref () : locale_(nullptr ) {}
2223
- template <typename Locale> explicit locale_ref (const Locale& loc);
2224
- explicit operator bool () const noexcept { return locale_ != nullptr ; }
2225
- #endif
2257
+
2258
+ template <typename Locale, FMT_ENABLE_IF(sizeof (Locale::collate) != 0 )>
2259
+ locale_ref (const Locale& loc);
2260
+
2261
+ inline explicit operator bool () const noexcept { return locale_ != nullptr ; }
2262
+ #endif // FMT_USE_LOCALE
2226
2263
2227
2264
template <typename Locale> auto get () const -> Locale;
2228
2265
};
@@ -2251,8 +2288,7 @@ template <typename Context, size_t NUM_ARGS, size_t NUM_NAMED_ARGS,
2251
2288
unsigned long long DESC>
2252
2289
struct named_arg_store {
2253
2290
// args_[0].named_args points to named_args to avoid bloating format_args.
2254
- // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
2255
- arg_t <Context, NUM_ARGS> args[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1 )];
2291
+ arg_t <Context, NUM_ARGS> args[1 + NUM_ARGS];
2256
2292
named_arg_info<typename Context::char_type> named_args[NUM_NAMED_ARGS];
2257
2293
2258
2294
template <typename ... T>
@@ -2286,7 +2322,7 @@ struct format_arg_store {
2286
2322
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
2287
2323
using type =
2288
2324
conditional_t <NUM_NAMED_ARGS == 0 ,
2289
- arg_t <Context, NUM_ARGS>[NUM_ARGS != 0 ? NUM_ARGS : + 1 ],
2325
+ arg_t <Context, NUM_ARGS>[max_of< size_t >( 1 , NUM_ARGS) ],
2290
2326
named_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>>;
2291
2327
type args;
2292
2328
};
@@ -2372,11 +2408,6 @@ template <typename T> class basic_appender {
2372
2408
detail::buffer<T>* container;
2373
2409
2374
2410
public:
2375
- using iterator_category = int ;
2376
- using value_type = T;
2377
- using pointer = T*;
2378
- using reference = T&;
2379
- using difference_type = decltype(pointer() - pointer());
2380
2411
using container_type = detail::buffer<T>;
2381
2412
2382
2413
FMT_CONSTEXPR basic_appender (detail::buffer<T>& buf) : container(&buf) {}
@@ -2596,7 +2627,7 @@ class context : private detail::locale_ref {
2596
2627
void operator =(const context&) = delete ;
2597
2628
2598
2629
FMT_CONSTEXPR auto arg (int id) const -> format_arg { return args_.get (id); }
2599
- auto arg (string_view name) -> format_arg { return args_.get (name); }
2630
+ inline auto arg (string_view name) -> format_arg { return args_.get (name); }
2600
2631
FMT_CONSTEXPR auto arg_id (string_view name) -> int {
2601
2632
return args_.get_id (name);
2602
2633
}
@@ -2605,7 +2636,7 @@ class context : private detail::locale_ref {
2605
2636
FMT_CONSTEXPR auto out () -> iterator { return out_; }
2606
2637
2607
2638
// Advances the begin iterator to `it`.
2608
- void advance_to (iterator) {}
2639
+ FMT_CONSTEXPR void advance_to (iterator) {}
2609
2640
2610
2641
FMT_CONSTEXPR auto locale () -> detail::locale_ref { return *this ; }
2611
2642
};
@@ -2627,12 +2658,14 @@ inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
2627
2658
// / A compile-time format string.
2628
2659
template <typename ... T> struct fstring {
2629
2660
private:
2630
- static constexpr int num_static_named_args =
2661
+ static constexpr size_t num_static_named_args =
2631
2662
detail::count_static_named_args<T...>();
2632
2663
2633
- using checker = detail::format_string_checker<
2634
- char , static_cast <int >(sizeof ...(T)), num_static_named_args,
2635
- num_static_named_args != detail::count_named_args<T...>()>;
2664
+ using checker =
2665
+ detail::format_string_checker<char , static_cast <int >(sizeof ...(T)),
2666
+ static_cast <int >(num_static_named_args),
2667
+ num_static_named_args !=
2668
+ detail::count_named_args<T...>()>;
2636
2669
2637
2670
using arg_pack = detail::arg_pack<T...>;
2638
2671
@@ -2657,8 +2690,9 @@ template <typename... T> struct fstring {
2657
2690
template <typename S,
2658
2691
FMT_ENABLE_IF (std::is_convertible<const S&, string_view>::value)>
2659
2692
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
2693
+ auto sv = string_view (str);
2660
2694
if (FMT_USE_CONSTEVAL)
2661
- detail::parse_format_string<char >(s , checker (s , arg_pack ()));
2695
+ detail::parse_format_string<char >(sv , checker (sv , arg_pack ()));
2662
2696
#ifdef FMT_ENFORCE_COMPILE_STRING
2663
2697
static_assert (
2664
2698
FMT_USE_CONSTEVAL && sizeof (s) != 0 ,
0 commit comments