mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-29 18:27:40 +02:00
Module linkage fixes for shared build (#4169)
* Mark some in-class defined member functions as explicitly inline/constexpr, to avoid missing external symbols when using fmt module with shared build due to modules not defaulting to implicit inline. * Switch constexpr to inline for context::arg(string_view). NOTE: Looks as if basic_format_args::get(string_view) could probably be made constexpr instead, but sticking with minimal change approach. * Work around apparent non-conformance of older MSVC compilers. * Switch format_int::str() from constexpr to inline to satisfy libstdc++ std::string constexpr limitations. * Replace usages of macros for constexpr/inline with keywords. * Fix for locations requiring C++14 constexpr. * Further minor constexpr tweaks. * Apply clang format
This commit is contained in:
@ -1788,9 +1788,9 @@ template <typename T> class buffer {
|
||||
};
|
||||
|
||||
struct buffer_traits {
|
||||
explicit buffer_traits(size_t) {}
|
||||
auto count() const -> size_t { return 0; }
|
||||
auto limit(size_t size) -> size_t { return size; }
|
||||
constexpr explicit buffer_traits(size_t) {}
|
||||
constexpr auto count() const -> size_t { return 0; }
|
||||
constexpr auto limit(size_t size) const -> size_t { return size; }
|
||||
};
|
||||
|
||||
class fixed_buffer_traits {
|
||||
@ -1799,9 +1799,9 @@ class fixed_buffer_traits {
|
||||
size_t limit_;
|
||||
|
||||
public:
|
||||
explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
|
||||
auto count() const -> size_t { return count_; }
|
||||
auto limit(size_t size) -> size_t {
|
||||
constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
|
||||
constexpr auto count() const -> size_t { return count_; }
|
||||
FMT_CONSTEXPR auto limit(size_t size) -> size_t {
|
||||
size_t n = limit_ > count_ ? limit_ - count_ : 0;
|
||||
count_ += size;
|
||||
return size < n ? size : n;
|
||||
@ -2224,7 +2224,7 @@ struct locale_ref {
|
||||
template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)>
|
||||
locale_ref(const Locale& loc);
|
||||
|
||||
explicit operator bool() const noexcept { return locale_ != nullptr; }
|
||||
inline explicit operator bool() const noexcept { return locale_ != nullptr; }
|
||||
#endif // FMT_USE_LOCALE
|
||||
|
||||
template <typename Locale> auto get() const -> Locale;
|
||||
@ -2599,7 +2599,7 @@ class context : private detail::locale_ref {
|
||||
void operator=(const context&) = delete;
|
||||
|
||||
FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); }
|
||||
auto arg(string_view name) -> format_arg { return args_.get(name); }
|
||||
inline auto arg(string_view name) -> format_arg { return args_.get(name); }
|
||||
FMT_CONSTEXPR auto arg_id(string_view name) -> int {
|
||||
return args_.get_id(name);
|
||||
}
|
||||
@ -2608,7 +2608,7 @@ class context : private detail::locale_ref {
|
||||
FMT_CONSTEXPR auto out() -> iterator { return out_; }
|
||||
|
||||
// Advances the begin iterator to `it`.
|
||||
void advance_to(iterator) {}
|
||||
FMT_CONSTEXPR void advance_to(iterator) {}
|
||||
|
||||
FMT_CONSTEXPR auto locale() -> detail::locale_ref { return *this; }
|
||||
};
|
||||
|
@ -540,24 +540,24 @@ inline auto localtime(std::time_t time) -> std::tm {
|
||||
std::time_t time_;
|
||||
std::tm tm_;
|
||||
|
||||
dispatcher(std::time_t t) : time_(t) {}
|
||||
inline dispatcher(std::time_t t) : time_(t) {}
|
||||
|
||||
auto run() -> bool {
|
||||
inline auto run() -> bool {
|
||||
using namespace fmt::detail;
|
||||
return handle(localtime_r(&time_, &tm_));
|
||||
}
|
||||
|
||||
auto handle(std::tm* tm) -> bool { return tm != nullptr; }
|
||||
inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
|
||||
|
||||
auto handle(detail::null<>) -> bool {
|
||||
inline auto handle(detail::null<>) -> bool {
|
||||
using namespace fmt::detail;
|
||||
return fallback(localtime_s(&tm_, &time_));
|
||||
}
|
||||
|
||||
auto fallback(int res) -> bool { return res == 0; }
|
||||
inline auto fallback(int res) -> bool { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VERSION
|
||||
auto fallback(detail::null<>) -> bool {
|
||||
inline auto fallback(detail::null<>) -> bool {
|
||||
using namespace fmt::detail;
|
||||
std::tm* tm = std::localtime(&time_);
|
||||
if (tm) tm_ = *tm;
|
||||
@ -591,24 +591,24 @@ inline auto gmtime(std::time_t time) -> std::tm {
|
||||
std::time_t time_;
|
||||
std::tm tm_;
|
||||
|
||||
dispatcher(std::time_t t) : time_(t) {}
|
||||
inline dispatcher(std::time_t t) : time_(t) {}
|
||||
|
||||
auto run() -> bool {
|
||||
inline auto run() -> bool {
|
||||
using namespace fmt::detail;
|
||||
return handle(gmtime_r(&time_, &tm_));
|
||||
}
|
||||
|
||||
auto handle(std::tm* tm) -> bool { return tm != nullptr; }
|
||||
inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
|
||||
|
||||
auto handle(detail::null<>) -> bool {
|
||||
inline auto handle(detail::null<>) -> bool {
|
||||
using namespace fmt::detail;
|
||||
return fallback(gmtime_s(&tm_, &time_));
|
||||
}
|
||||
|
||||
auto fallback(int res) -> bool { return res == 0; }
|
||||
inline auto fallback(int res) -> bool { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VERSION
|
||||
auto fallback(detail::null<>) -> bool {
|
||||
inline auto fallback(detail::null<>) -> bool {
|
||||
std::tm* tm = std::gmtime(&time_);
|
||||
if (tm) tm_ = *tm;
|
||||
return tm != nullptr;
|
||||
@ -912,7 +912,9 @@ template <typename Derived> struct null_chrono_spec_handler {
|
||||
};
|
||||
|
||||
struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {
|
||||
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); }
|
||||
FMT_NORETURN inline void unsupported() {
|
||||
FMT_THROW(format_error("no format"));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||
@ -1572,7 +1574,7 @@ class tm_writer {
|
||||
struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
|
||||
bool has_precision_integral = false;
|
||||
|
||||
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); }
|
||||
FMT_NORETURN inline void unsupported() { FMT_THROW(format_error("no date")); }
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||
@ -1693,14 +1695,14 @@ class get_locale {
|
||||
bool has_locale_ = false;
|
||||
|
||||
public:
|
||||
get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
|
||||
inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
|
||||
if (localized)
|
||||
::new (&locale_) std::locale(loc.template get<std::locale>());
|
||||
}
|
||||
~get_locale() {
|
||||
inline ~get_locale() {
|
||||
if (has_locale_) locale_.~locale();
|
||||
}
|
||||
operator const std::locale&() const {
|
||||
inline operator const std::locale&() const {
|
||||
return has_locale_ ? locale_ : get_classic_locale();
|
||||
}
|
||||
};
|
||||
|
@ -372,13 +372,14 @@ class uint128_fallback {
|
||||
-> uint128_fallback {
|
||||
return {~n.hi_, ~n.lo_};
|
||||
}
|
||||
friend auto operator+(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs) -> uint128_fallback {
|
||||
friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs,
|
||||
const uint128_fallback& rhs)
|
||||
-> uint128_fallback {
|
||||
auto result = uint128_fallback(lhs);
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
|
||||
friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs)
|
||||
-> uint128_fallback {
|
||||
FMT_ASSERT(lhs.hi_ == 0, "");
|
||||
uint64_t hi = (lhs.lo_ >> 32) * rhs;
|
||||
@ -386,7 +387,7 @@ class uint128_fallback {
|
||||
uint64_t new_lo = (hi << 32) + lo;
|
||||
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
|
||||
}
|
||||
friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
|
||||
friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs)
|
||||
-> uint128_fallback {
|
||||
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
|
||||
}
|
||||
@ -955,8 +956,8 @@ class writer {
|
||||
FILE* file_;
|
||||
|
||||
public:
|
||||
writer(FILE* f) : buf_(nullptr), file_(f) {}
|
||||
writer(detail::buffer<char>& buf) : buf_(&buf) {}
|
||||
inline writer(FILE* f) : buf_(nullptr), file_(f) {}
|
||||
inline writer(detail::buffer<char>& buf) : buf_(&buf) {}
|
||||
|
||||
/// Formats `args` according to specifications in `fmt` and writes the
|
||||
/// output to the file.
|
||||
@ -974,10 +975,10 @@ class string_buffer {
|
||||
detail::container_buffer<std::string> buf_;
|
||||
|
||||
public:
|
||||
string_buffer() : buf_(str_) {}
|
||||
inline string_buffer() : buf_(str_) {}
|
||||
|
||||
operator writer() { return buf_; }
|
||||
std::string& str() { return str_; }
|
||||
inline operator writer() { return buf_; }
|
||||
inline std::string& str() { return str_; }
|
||||
};
|
||||
|
||||
template <typename T, size_t SIZE, typename Allocator>
|
||||
@ -1418,10 +1419,12 @@ class utf8_to_utf16 {
|
||||
|
||||
public:
|
||||
FMT_API explicit utf8_to_utf16(string_view s);
|
||||
operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
|
||||
auto size() const -> size_t { return buffer_.size() - 1; }
|
||||
auto c_str() const -> const wchar_t* { return &buffer_[0]; }
|
||||
auto str() const -> std::wstring { return {&buffer_[0], size()}; }
|
||||
inline operator basic_string_view<wchar_t>() const {
|
||||
return {&buffer_[0], size()};
|
||||
}
|
||||
inline auto size() const -> size_t { return buffer_.size() - 1; }
|
||||
inline auto c_str() const -> const wchar_t* { return &buffer_[0]; }
|
||||
inline auto str() const -> std::wstring { return {&buffer_[0], size()}; }
|
||||
};
|
||||
|
||||
enum class to_utf8_error_policy { abort, replace };
|
||||
@ -3927,7 +3930,7 @@ template <> struct formatter<std::byte> : formatter<unsigned> {
|
||||
struct bytes {
|
||||
string_view data;
|
||||
|
||||
explicit bytes(string_view s) : data(s) {}
|
||||
inline explicit bytes(string_view s) : data(s) {}
|
||||
};
|
||||
|
||||
template <> struct formatter<bytes> {
|
||||
@ -4131,7 +4134,7 @@ class format_int {
|
||||
}
|
||||
|
||||
/// Returns the content of the output buffer as an `std::string`.
|
||||
auto str() const -> std::string { return {str_, size()}; }
|
||||
inline auto str() const -> std::string { return {str_, size()}; }
|
||||
};
|
||||
|
||||
#define FMT_STRING_IMPL(s, base) \
|
||||
|
@ -176,24 +176,24 @@ class buffered_file {
|
||||
|
||||
friend class file;
|
||||
|
||||
explicit buffered_file(FILE* f) : file_(f) {}
|
||||
inline explicit buffered_file(FILE* f) : file_(f) {}
|
||||
|
||||
public:
|
||||
buffered_file(const buffered_file&) = delete;
|
||||
void operator=(const buffered_file&) = delete;
|
||||
|
||||
// Constructs a buffered_file object which doesn't represent any file.
|
||||
buffered_file() noexcept : file_(nullptr) {}
|
||||
inline buffered_file() noexcept : file_(nullptr) {}
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
FMT_API ~buffered_file() noexcept;
|
||||
|
||||
public:
|
||||
buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
|
||||
inline buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
|
||||
auto operator=(buffered_file&& other) -> buffered_file& {
|
||||
inline auto operator=(buffered_file&& other) -> buffered_file& {
|
||||
close();
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
@ -207,7 +207,7 @@ class buffered_file {
|
||||
FMT_API void close();
|
||||
|
||||
// Returns the pointer to a FILE object representing this file.
|
||||
auto get() const noexcept -> FILE* { return file_; }
|
||||
inline auto get() const noexcept -> FILE* { return file_; }
|
||||
|
||||
FMT_API auto descriptor() const -> int;
|
||||
|
||||
@ -248,7 +248,7 @@ class FMT_API file {
|
||||
};
|
||||
|
||||
// Constructs a file object which doesn't represent any file.
|
||||
file() noexcept : fd_(-1) {}
|
||||
inline file() noexcept : fd_(-1) {}
|
||||
|
||||
// Opens a file and constructs a file object representing this file.
|
||||
file(cstring_view path, int oflag);
|
||||
@ -257,10 +257,10 @@ class FMT_API file {
|
||||
file(const file&) = delete;
|
||||
void operator=(const file&) = delete;
|
||||
|
||||
file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
|
||||
inline file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
|
||||
|
||||
// Move assignment is not noexcept because close may throw.
|
||||
auto operator=(file&& other) -> file& {
|
||||
inline auto operator=(file&& other) -> file& {
|
||||
close();
|
||||
fd_ = other.fd_;
|
||||
other.fd_ = -1;
|
||||
@ -271,7 +271,7 @@ class FMT_API file {
|
||||
~file() noexcept;
|
||||
|
||||
// Returns the file descriptor.
|
||||
auto descriptor() const noexcept -> int { return fd_; }
|
||||
inline auto descriptor() const noexcept -> int { return fd_; }
|
||||
|
||||
// Closes the file.
|
||||
void close();
|
||||
@ -324,9 +324,9 @@ auto getpagesize() -> long;
|
||||
namespace detail {
|
||||
|
||||
struct buffer_size {
|
||||
buffer_size() = default;
|
||||
constexpr buffer_size() = default;
|
||||
size_t value = 0;
|
||||
auto operator=(size_t val) const -> buffer_size {
|
||||
FMT_CONSTEXPR auto operator=(size_t val) const -> buffer_size {
|
||||
auto bs = buffer_size();
|
||||
bs.value = val;
|
||||
return bs;
|
||||
@ -337,7 +337,7 @@ struct ostream_params {
|
||||
int oflag = file::WRONLY | file::CREATE | file::TRUNC;
|
||||
size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
|
||||
|
||||
ostream_params() {}
|
||||
constexpr ostream_params() {}
|
||||
|
||||
template <typename... T>
|
||||
ostream_params(T... params, int new_oflag) : ostream_params(params...) {
|
||||
@ -381,7 +381,7 @@ class FMT_API ostream : private detail::buffer<char> {
|
||||
return buf;
|
||||
}
|
||||
|
||||
void flush() {
|
||||
inline void flush() {
|
||||
if (size() == 0) return;
|
||||
file_.write(data(), size() * sizeof(data()[0]));
|
||||
clear();
|
||||
@ -390,7 +390,7 @@ class FMT_API ostream : private detail::buffer<char> {
|
||||
template <typename... T>
|
||||
friend auto output_file(cstring_view path, T... params) -> ostream;
|
||||
|
||||
void close() {
|
||||
inline void close() {
|
||||
flush();
|
||||
file_.close();
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ template <bool IsSigned> struct int_checker {
|
||||
unsigned max = to_unsigned(max_value<int>());
|
||||
return value <= max;
|
||||
}
|
||||
static auto fits_in_int(bool) -> bool { return true; }
|
||||
inline static auto fits_in_int(bool) -> bool { return true; }
|
||||
};
|
||||
|
||||
template <> struct int_checker<true> {
|
||||
@ -87,7 +87,7 @@ template <> struct int_checker<true> {
|
||||
return value >= (std::numeric_limits<int>::min)() &&
|
||||
value <= max_value<int>();
|
||||
}
|
||||
static auto fits_in_int(int) -> bool { return true; }
|
||||
inline static auto fits_in_int(int) -> bool { return true; }
|
||||
};
|
||||
|
||||
struct printf_precision_handler {
|
||||
@ -205,7 +205,7 @@ class printf_width_handler {
|
||||
format_specs& specs_;
|
||||
|
||||
public:
|
||||
explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
|
||||
inline explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
auto operator()(T value) -> unsigned {
|
||||
|
Reference in New Issue
Block a user