Skip to content

Commit 96dca56

Browse files
authored
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
1 parent 891c9a7 commit 96dca56

File tree

5 files changed

+63
-58
lines changed

5 files changed

+63
-58
lines changed

include/fmt/base.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,9 +1788,9 @@ template <typename T> class buffer {
17881788
};
17891789

17901790
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; }
1791+
constexpr explicit buffer_traits(size_t) {}
1792+
constexpr auto count() const -> size_t { return 0; }
1793+
constexpr auto limit(size_t size) const -> size_t { return size; }
17941794
};
17951795

17961796
class fixed_buffer_traits {
@@ -1799,9 +1799,9 @@ class fixed_buffer_traits {
17991799
size_t limit_;
18001800

18011801
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 {
1802+
constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
1803+
constexpr auto count() const -> size_t { return count_; }
1804+
FMT_CONSTEXPR auto limit(size_t size) -> size_t {
18051805
size_t n = limit_ > count_ ? limit_ - count_ : 0;
18061806
count_ += size;
18071807
return size < n ? size : n;
@@ -2224,7 +2224,7 @@ struct locale_ref {
22242224
template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)>
22252225
locale_ref(const Locale& loc);
22262226

2227-
explicit operator bool() const noexcept { return locale_ != nullptr; }
2227+
inline explicit operator bool() const noexcept { return locale_ != nullptr; }
22282228
#endif // FMT_USE_LOCALE
22292229

22302230
template <typename Locale> auto get() const -> Locale;
@@ -2599,7 +2599,7 @@ class context : private detail::locale_ref {
25992599
void operator=(const context&) = delete;
26002600

26012601
FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); }
2602-
auto arg(string_view name) -> format_arg { return args_.get(name); }
2602+
inline auto arg(string_view name) -> format_arg { return args_.get(name); }
26032603
FMT_CONSTEXPR auto arg_id(string_view name) -> int {
26042604
return args_.get_id(name);
26052605
}
@@ -2608,7 +2608,7 @@ class context : private detail::locale_ref {
26082608
FMT_CONSTEXPR auto out() -> iterator { return out_; }
26092609

26102610
// Advances the begin iterator to `it`.
2611-
void advance_to(iterator) {}
2611+
FMT_CONSTEXPR void advance_to(iterator) {}
26122612

26132613
FMT_CONSTEXPR auto locale() -> detail::locale_ref { return *this; }
26142614
};

include/fmt/chrono.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -540,24 +540,24 @@ inline auto localtime(std::time_t time) -> std::tm {
540540
std::time_t time_;
541541
std::tm tm_;
542542

543-
dispatcher(std::time_t t) : time_(t) {}
543+
inline dispatcher(std::time_t t) : time_(t) {}
544544

545-
auto run() -> bool {
545+
inline auto run() -> bool {
546546
using namespace fmt::detail;
547547
return handle(localtime_r(&time_, &tm_));
548548
}
549549

550-
auto handle(std::tm* tm) -> bool { return tm != nullptr; }
550+
inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
551551

552-
auto handle(detail::null<>) -> bool {
552+
inline auto handle(detail::null<>) -> bool {
553553
using namespace fmt::detail;
554554
return fallback(localtime_s(&tm_, &time_));
555555
}
556556

557-
auto fallback(int res) -> bool { return res == 0; }
557+
inline auto fallback(int res) -> bool { return res == 0; }
558558

559559
#if !FMT_MSC_VERSION
560-
auto fallback(detail::null<>) -> bool {
560+
inline auto fallback(detail::null<>) -> bool {
561561
using namespace fmt::detail;
562562
std::tm* tm = std::localtime(&time_);
563563
if (tm) tm_ = *tm;
@@ -591,24 +591,24 @@ inline auto gmtime(std::time_t time) -> std::tm {
591591
std::time_t time_;
592592
std::tm tm_;
593593

594-
dispatcher(std::time_t t) : time_(t) {}
594+
inline dispatcher(std::time_t t) : time_(t) {}
595595

596-
auto run() -> bool {
596+
inline auto run() -> bool {
597597
using namespace fmt::detail;
598598
return handle(gmtime_r(&time_, &tm_));
599599
}
600600

601-
auto handle(std::tm* tm) -> bool { return tm != nullptr; }
601+
inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
602602

603-
auto handle(detail::null<>) -> bool {
603+
inline auto handle(detail::null<>) -> bool {
604604
using namespace fmt::detail;
605605
return fallback(gmtime_s(&tm_, &time_));
606606
}
607607

608-
auto fallback(int res) -> bool { return res == 0; }
608+
inline auto fallback(int res) -> bool { return res == 0; }
609609

610610
#if !FMT_MSC_VERSION
611-
auto fallback(detail::null<>) -> bool {
611+
inline auto fallback(detail::null<>) -> bool {
612612
std::tm* tm = std::gmtime(&time_);
613613
if (tm) tm_ = *tm;
614614
return tm != nullptr;
@@ -912,7 +912,9 @@ template <typename Derived> struct null_chrono_spec_handler {
912912
};
913913

914914
struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {
915-
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); }
915+
FMT_NORETURN inline void unsupported() {
916+
FMT_THROW(format_error("no format"));
917+
}
916918

917919
template <typename Char>
918920
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
@@ -1572,7 +1574,7 @@ class tm_writer {
15721574
struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
15731575
bool has_precision_integral = false;
15741576

1575-
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); }
1577+
FMT_NORETURN inline void unsupported() { FMT_THROW(format_error("no date")); }
15761578

15771579
template <typename Char>
15781580
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
@@ -1693,14 +1695,14 @@ class get_locale {
16931695
bool has_locale_ = false;
16941696

16951697
public:
1696-
get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
1698+
inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
16971699
if (localized)
16981700
::new (&locale_) std::locale(loc.template get<std::locale>());
16991701
}
1700-
~get_locale() {
1702+
inline ~get_locale() {
17011703
if (has_locale_) locale_.~locale();
17021704
}
1703-
operator const std::locale&() const {
1705+
inline operator const std::locale&() const {
17041706
return has_locale_ ? locale_ : get_classic_locale();
17051707
}
17061708
};

include/fmt/format.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -372,21 +372,22 @@ class uint128_fallback {
372372
-> uint128_fallback {
373373
return {~n.hi_, ~n.lo_};
374374
}
375-
friend auto operator+(const uint128_fallback& lhs,
376-
const uint128_fallback& rhs) -> uint128_fallback {
375+
friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs,
376+
const uint128_fallback& rhs)
377+
-> uint128_fallback {
377378
auto result = uint128_fallback(lhs);
378379
result += rhs;
379380
return result;
380381
}
381-
friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
382+
friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs)
382383
-> uint128_fallback {
383384
FMT_ASSERT(lhs.hi_ == 0, "");
384385
uint64_t hi = (lhs.lo_ >> 32) * rhs;
385386
uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
386387
uint64_t new_lo = (hi << 32) + lo;
387388
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
388389
}
389-
friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
390+
friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs)
390391
-> uint128_fallback {
391392
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
392393
}
@@ -955,8 +956,8 @@ class writer {
955956
FILE* file_;
956957

957958
public:
958-
writer(FILE* f) : buf_(nullptr), file_(f) {}
959-
writer(detail::buffer<char>& buf) : buf_(&buf) {}
959+
inline writer(FILE* f) : buf_(nullptr), file_(f) {}
960+
inline writer(detail::buffer<char>& buf) : buf_(&buf) {}
960961

961962
/// Formats `args` according to specifications in `fmt` and writes the
962963
/// output to the file.
@@ -974,10 +975,10 @@ class string_buffer {
974975
detail::container_buffer<std::string> buf_;
975976

976977
public:
977-
string_buffer() : buf_(str_) {}
978+
inline string_buffer() : buf_(str_) {}
978979

979-
operator writer() { return buf_; }
980-
std::string& str() { return str_; }
980+
inline operator writer() { return buf_; }
981+
inline std::string& str() { return str_; }
981982
};
982983

983984
template <typename T, size_t SIZE, typename Allocator>
@@ -1418,10 +1419,12 @@ class utf8_to_utf16 {
14181419

14191420
public:
14201421
FMT_API explicit utf8_to_utf16(string_view s);
1421-
operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
1422-
auto size() const -> size_t { return buffer_.size() - 1; }
1423-
auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1424-
auto str() const -> std::wstring { return {&buffer_[0], size()}; }
1422+
inline operator basic_string_view<wchar_t>() const {
1423+
return {&buffer_[0], size()};
1424+
}
1425+
inline auto size() const -> size_t { return buffer_.size() - 1; }
1426+
inline auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1427+
inline auto str() const -> std::wstring { return {&buffer_[0], size()}; }
14251428
};
14261429

14271430
enum class to_utf8_error_policy { abort, replace };
@@ -3927,7 +3930,7 @@ template <> struct formatter<std::byte> : formatter<unsigned> {
39273930
struct bytes {
39283931
string_view data;
39293932

3930-
explicit bytes(string_view s) : data(s) {}
3933+
inline explicit bytes(string_view s) : data(s) {}
39313934
};
39323935

39333936
template <> struct formatter<bytes> {
@@ -4131,7 +4134,7 @@ class format_int {
41314134
}
41324135

41334136
/// Returns the content of the output buffer as an `std::string`.
4134-
auto str() const -> std::string { return {str_, size()}; }
4137+
inline auto str() const -> std::string { return {str_, size()}; }
41354138
};
41364139

41374140
#define FMT_STRING_IMPL(s, base) \

include/fmt/os.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,24 +176,24 @@ class buffered_file {
176176

177177
friend class file;
178178

179-
explicit buffered_file(FILE* f) : file_(f) {}
179+
inline explicit buffered_file(FILE* f) : file_(f) {}
180180

181181
public:
182182
buffered_file(const buffered_file&) = delete;
183183
void operator=(const buffered_file&) = delete;
184184

185185
// Constructs a buffered_file object which doesn't represent any file.
186-
buffered_file() noexcept : file_(nullptr) {}
186+
inline buffered_file() noexcept : file_(nullptr) {}
187187

188188
// Destroys the object closing the file it represents if any.
189189
FMT_API ~buffered_file() noexcept;
190190

191191
public:
192-
buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
192+
inline buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
193193
other.file_ = nullptr;
194194
}
195195

196-
auto operator=(buffered_file&& other) -> buffered_file& {
196+
inline auto operator=(buffered_file&& other) -> buffered_file& {
197197
close();
198198
file_ = other.file_;
199199
other.file_ = nullptr;
@@ -207,7 +207,7 @@ class buffered_file {
207207
FMT_API void close();
208208

209209
// Returns the pointer to a FILE object representing this file.
210-
auto get() const noexcept -> FILE* { return file_; }
210+
inline auto get() const noexcept -> FILE* { return file_; }
211211

212212
FMT_API auto descriptor() const -> int;
213213

@@ -248,7 +248,7 @@ class FMT_API file {
248248
};
249249

250250
// Constructs a file object which doesn't represent any file.
251-
file() noexcept : fd_(-1) {}
251+
inline file() noexcept : fd_(-1) {}
252252

253253
// Opens a file and constructs a file object representing this file.
254254
file(cstring_view path, int oflag);
@@ -257,10 +257,10 @@ class FMT_API file {
257257
file(const file&) = delete;
258258
void operator=(const file&) = delete;
259259

260-
file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
260+
inline file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
261261

262262
// Move assignment is not noexcept because close may throw.
263-
auto operator=(file&& other) -> file& {
263+
inline auto operator=(file&& other) -> file& {
264264
close();
265265
fd_ = other.fd_;
266266
other.fd_ = -1;
@@ -271,7 +271,7 @@ class FMT_API file {
271271
~file() noexcept;
272272

273273
// Returns the file descriptor.
274-
auto descriptor() const noexcept -> int { return fd_; }
274+
inline auto descriptor() const noexcept -> int { return fd_; }
275275

276276
// Closes the file.
277277
void close();
@@ -324,9 +324,9 @@ auto getpagesize() -> long;
324324
namespace detail {
325325

326326
struct buffer_size {
327-
buffer_size() = default;
327+
constexpr buffer_size() = default;
328328
size_t value = 0;
329-
auto operator=(size_t val) const -> buffer_size {
329+
FMT_CONSTEXPR auto operator=(size_t val) const -> buffer_size {
330330
auto bs = buffer_size();
331331
bs.value = val;
332332
return bs;
@@ -337,7 +337,7 @@ struct ostream_params {
337337
int oflag = file::WRONLY | file::CREATE | file::TRUNC;
338338
size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
339339

340-
ostream_params() {}
340+
constexpr ostream_params() {}
341341

342342
template <typename... T>
343343
ostream_params(T... params, int new_oflag) : ostream_params(params...) {
@@ -381,7 +381,7 @@ class FMT_API ostream : private detail::buffer<char> {
381381
return buf;
382382
}
383383

384-
void flush() {
384+
inline void flush() {
385385
if (size() == 0) return;
386386
file_.write(data(), size() * sizeof(data()[0]));
387387
clear();
@@ -390,7 +390,7 @@ class FMT_API ostream : private detail::buffer<char> {
390390
template <typename... T>
391391
friend auto output_file(cstring_view path, T... params) -> ostream;
392392

393-
void close() {
393+
inline void close() {
394394
flush();
395395
file_.close();
396396
}

include/fmt/printf.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@ template <bool IsSigned> struct int_checker {
7979
unsigned max = to_unsigned(max_value<int>());
8080
return value <= max;
8181
}
82-
static auto fits_in_int(bool) -> bool { return true; }
82+
inline static auto fits_in_int(bool) -> bool { return true; }
8383
};
8484

8585
template <> struct int_checker<true> {
8686
template <typename T> static auto fits_in_int(T value) -> bool {
8787
return value >= (std::numeric_limits<int>::min)() &&
8888
value <= max_value<int>();
8989
}
90-
static auto fits_in_int(int) -> bool { return true; }
90+
inline static auto fits_in_int(int) -> bool { return true; }
9191
};
9292

9393
struct printf_precision_handler {
@@ -205,7 +205,7 @@ class printf_width_handler {
205205
format_specs& specs_;
206206

207207
public:
208-
explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
208+
inline explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
209209

210210
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
211211
auto operator()(T value) -> unsigned {

0 commit comments

Comments
 (0)