Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove fallback to inline specifier from FMT_CONSTEXPR(20) macro #2075

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 53 additions & 19 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,27 +456,61 @@ namespace detail {
template <typename Period> FMT_CONSTEXPR const char* get_units() {
return nullptr;
}
template <> FMT_CONSTEXPR const char* get_units<std::atto>() { return "as"; }
template <> FMT_CONSTEXPR const char* get_units<std::femto>() { return "fs"; }
template <> FMT_CONSTEXPR const char* get_units<std::pico>() { return "ps"; }
template <> FMT_CONSTEXPR const char* get_units<std::nano>() { return "ns"; }
template <> FMT_CONSTEXPR const char* get_units<std::micro>() { return "µs"; }
template <> FMT_CONSTEXPR const char* get_units<std::milli>() { return "ms"; }
template <> FMT_CONSTEXPR const char* get_units<std::centi>() { return "cs"; }
template <> FMT_CONSTEXPR const char* get_units<std::deci>() { return "ds"; }
template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; }
template <> FMT_CONSTEXPR const char* get_units<std::deca>() { return "das"; }
template <> FMT_CONSTEXPR const char* get_units<std::hecto>() { return "hs"; }
template <> FMT_CONSTEXPR const char* get_units<std::kilo>() { return "ks"; }
template <> FMT_CONSTEXPR const char* get_units<std::mega>() { return "Ms"; }
template <> FMT_CONSTEXPR const char* get_units<std::giga>() { return "Gs"; }
template <> FMT_CONSTEXPR const char* get_units<std::tera>() { return "Ts"; }
template <> FMT_CONSTEXPR const char* get_units<std::peta>() { return "Ps"; }
template <> FMT_CONSTEXPR const char* get_units<std::exa>() { return "Es"; }
template <> FMT_CONSTEXPR const char* get_units<std::ratio<60>>() {
template <> FMT_CONSTEXPR inline const char* get_units<std::atto>() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove inline from all these functions? Ideally all of this should be rewritten without template specializations but this is out of scope of the current PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It causes multiple definitions of these functions.
Maybe a test for multiple definitions can be added, which would include all headers in two object files and link them together. Because now I have to include chrono.h into util.h in the test directory to get this error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I don't think the multiple definition test is necessary.

return "as";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::femto>() {
return "fs";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::pico>() {
return "ps";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::nano>() {
return "ns";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::micro>() {
return "µs";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::milli>() {
return "ms";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::centi>() {
return "cs";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::deci>() {
return "ds";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<1>>() {
return "s";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::deca>() {
return "das";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::hecto>() {
return "hs";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::kilo>() {
return "ks";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::mega>() {
return "Ms";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::giga>() {
return "Gs";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::tera>() {
return "Ts";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::peta>() {
return "Ps";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::exa>() {
return "Es";
}
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<60>>() {
return "m";
}
template <> FMT_CONSTEXPR const char* get_units<std::ratio<3600>>() {
template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<3600>>() {
return "h";
}

Expand Down
7 changes: 4 additions & 3 deletions include/fmt/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,16 +353,17 @@ class text_style {
};

/** Creates a text style from the foreground (text) color. */
FMT_CONSTEXPR text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
return text_style(true, foreground);
}

/** Creates a text style from the background color. */
FMT_CONSTEXPR text_style bg(detail::color_type background) FMT_NOEXCEPT {
FMT_CONSTEXPR inline text_style bg(detail::color_type background) FMT_NOEXCEPT {
return text_style(false, background);
}

FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT {
FMT_CONSTEXPR inline text_style operator|(emphasis lhs,
emphasis rhs) FMT_NOEXCEPT {
return text_style(lhs) | rhs;
}

Expand Down
21 changes: 12 additions & 9 deletions include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
# define FMT_CONSTEXPR constexpr
# define FMT_CONSTEXPR_DECL constexpr
#else
# define FMT_CONSTEXPR inline
# define FMT_CONSTEXPR
# define FMT_CONSTEXPR_DECL
#endif

Expand Down Expand Up @@ -946,9 +946,9 @@ struct arg_data<T, Char, NUM_ARGS, 0> {
T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];

template <typename... U>
FMT_CONSTEXPR arg_data(const U&... init) : args_{init...} {}
FMT_CONSTEXPR const T* args() const { return args_; }
FMT_CONSTEXPR std::nullptr_t named_args() { return nullptr; }
FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {}
FMT_CONSTEXPR FMT_INLINE const T* args() const { return args_; }
FMT_CONSTEXPR FMT_INLINE std::nullptr_t named_args() { return nullptr; }
};

template <typename Char>
Expand All @@ -969,7 +969,8 @@ void init_named_args(named_arg_info<Char>* named_args, int arg_count,
}

template <typename... Args>
FMT_CONSTEXPR void init_named_args(std::nullptr_t, int, int, const Args&...) {}
FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int,
const Args&...) {}

template <typename T> struct is_named_arg : std::false_type {};

Expand Down Expand Up @@ -1090,11 +1091,11 @@ template <typename Context> class value {
FMT_INLINE value(long double val) : long_double_value(val) {}
constexpr FMT_INLINE value(bool val) : bool_value(val) {}
constexpr FMT_INLINE value(char_type val) : char_value(val) {}
FMT_CONSTEXPR value(const char_type* val) {
FMT_CONSTEXPR FMT_INLINE value(const char_type* val) {
string.data = val;
if (is_constant_evaluated()) string.size = {};
}
FMT_CONSTEXPR value(basic_string_view<char_type> val) {
FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) {
string.data = val.data();
string.size = val.size();
}
Expand Down Expand Up @@ -1685,7 +1686,8 @@ template <typename Context> class basic_format_args {
\endrst
*/
template <typename... Args>
constexpr basic_format_args(const format_arg_store<Context, Args...>& store)
constexpr FMT_INLINE basic_format_args(
const format_arg_store<Context, Args...>& store)
: basic_format_args(store.desc, store.data_.args()) {}

/**
Expand All @@ -1694,7 +1696,8 @@ template <typename Context> class basic_format_args {
`~fmt::dynamic_format_arg_store`.
\endrst
*/
constexpr basic_format_args(const dynamic_format_arg_store<Context>& store)
constexpr FMT_INLINE basic_format_args(
const dynamic_format_arg_store<Context>& store)
: basic_format_args(store.get_types(), store.data()) {}

/**
Expand Down
28 changes: 16 additions & 12 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ namespace detail {
(__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002)
# define FMT_CONSTEXPR20 constexpr
#else
# define FMT_CONSTEXPR20 inline
# define FMT_CONSTEXPR20
#endif

// An equivalent of `*reinterpret_cast<Dest*>(&source)` that doesn't have
Expand Down Expand Up @@ -545,7 +545,7 @@ inline size_t count_code_points(basic_string_view<Char> s) {
}

// Counts the number of code points in a UTF-8 string.
FMT_CONSTEXPR size_t count_code_points(basic_string_view<char> s) {
FMT_CONSTEXPR inline size_t count_code_points(basic_string_view<char> s) {
const char* data = s.data();
size_t num_code_points = 0;
for (size_t i = 0, size = s.size(); i != size; ++i) {
Expand Down Expand Up @@ -984,7 +984,7 @@ template <typename T> FMT_CONSTEXPR int count_digits_fallback(T n) {
#ifdef FMT_BUILTIN_CLZLL
// Returns the number of decimal digits in n. Leading zeros are not counted
// except for n == 0 in which case count_digits returns 1.
FMT_CONSTEXPR20 int count_digits(uint64_t n) {
FMT_CONSTEXPR20 inline int count_digits(uint64_t n) {
if (is_constant_evaluated()) {
return count_digits_fallback(n);
}
Expand All @@ -994,11 +994,13 @@ FMT_CONSTEXPR20 int count_digits(uint64_t n) {
}
#else
// Fallback version of count_digits used when __builtin_clz is not available.
FMT_CONSTEXPR int count_digits(uint64_t n) { return count_digits_fallback(n); }
FMT_CONSTEXPR inline int count_digits(uint64_t n) {
return count_digits_fallback(n);
}
#endif

#if FMT_USE_INT128
FMT_CONSTEXPR int count_digits(uint128_t n) {
FMT_CONSTEXPR inline int count_digits(uint128_t n) {
int count = 1;
for (;;) {
// Integer division is slow so do it for a group of four digits instead
Expand Down Expand Up @@ -1035,7 +1037,7 @@ template <> int count_digits<4>(detail::fallback_uintptr n);

#ifdef FMT_BUILTIN_CLZ
// Optional version of count_digits for better performance on 32-bit platforms.
FMT_CONSTEXPR20 int count_digits(uint32_t n) {
FMT_CONSTEXPR20 inline int count_digits(uint32_t n) {
if (is_constant_evaluated()) {
return count_digits_fallback(n);
}
Expand Down Expand Up @@ -2315,7 +2317,7 @@ class arg_formatter_base {
}

template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
FMT_CONSTEXPR iterator operator()(T value) {
FMT_CONSTEXPR FMT_INLINE iterator operator()(T value) {
if (specs_)
write_int(value, *specs_);
else
Expand Down Expand Up @@ -4034,11 +4036,11 @@ FMT_CONSTEXPR detail::udl_formatter<Char, CHARS...> operator""_format() {
std::string message = "The answer is {}"_format(42);
\endrst
*/
FMT_CONSTEXPR detail::udl_formatter<char> operator"" _format(const char* s,
size_t n) {
FMT_CONSTEXPR inline detail::udl_formatter<char> operator"" _format(
const char* s, size_t n) {
return {{s, n}};
}
FMT_CONSTEXPR detail::udl_formatter<wchar_t> operator"" _format(
FMT_CONSTEXPR inline detail::udl_formatter<wchar_t> operator"" _format(
const wchar_t* s, size_t n) {
return {{s, n}};
}
Expand All @@ -4054,10 +4056,12 @@ FMT_CONSTEXPR detail::udl_formatter<wchar_t> operator"" _format(
fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
\endrst
*/
FMT_CONSTEXPR detail::udl_arg<char> operator"" _a(const char* s, size_t) {
FMT_CONSTEXPR inline detail::udl_arg<char> operator"" _a(const char* s,
size_t) {
return {s};
}
FMT_CONSTEXPR detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
FMT_CONSTEXPR inline detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s,
size_t) {
return {s};
}
} // namespace literals
Expand Down