Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
src: avoid unnecessary string allocations in SPrintF impl
If we can use a `std::string_view` instead of a `std::string`, let's
just do that instead.
  • Loading branch information
addaleax committed Sep 28, 2025
commit c9bad7987d85dcb91c1f4357fd9d46c35156cda6
45 changes: 33 additions & 12 deletions src/debug_utils-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,41 @@

namespace node {

template <typename T>
concept StringViewConvertible = requires(T a) {
{
a.ToStringView()
} -> std::convertible_to<std::string_view>;
};
template <typename T>
concept StringConvertible = requires(T a) {
{
a.ToString()
} -> std::convertible_to<std::string>;
};

struct ToStringHelper {
template <typename T>
static std::string Convert(
const T& value,
std::string(T::* to_string)() const = &T::ToString) {
return (value.*to_string)();
requires(StringConvertible<T>) && (!StringViewConvertible<T>)
static std::string Convert(const T& value) {
return value.ToString();
}
template <typename T>
requires StringViewConvertible<T>
static std::string_view Convert(const T& value) {
return value.ToStringView();
}

template <typename T,
typename test_for_number = typename std::
enable_if<std::is_arithmetic<T>::value, bool>::type,
typename dummy = bool>
static std::string Convert(const T& value) { return std::to_string(value); }
static std::string Convert(const char* value) {
static std::string_view Convert(const char* value) {
return value != nullptr ? value : "(null)";
}
static std::string Convert(const std::string& value) { return value; }
static std::string Convert(std::string_view value) {
return std::string(value);
}
static std::string_view Convert(std::string_view value) { return value; }
static std::string Convert(bool value) { return value ? "true" : "false"; }
template <unsigned BASE_BITS,
typename T,
Expand All @@ -50,18 +66,23 @@ struct ToStringHelper {
template <unsigned BASE_BITS,
typename T,
typename = std::enable_if_t<!std::is_integral_v<T>>>
static std::string BaseConvert(T& value) { // NOLINT(runtime/references)
static auto BaseConvert(T&& value) {
return Convert(std::forward<T>(value));
}
};

template <typename T>
std::string ToString(const T& value) {
auto ToStringOrStringView(const T& value) {
return ToStringHelper::Convert(value);
}

template <typename T>
std::string ToString(const T& value) {
return std::string(ToStringOrStringView(value));
}

template <unsigned BASE_BITS, typename T>
std::string ToBaseString(const T& value) {
auto ToBaseString(const T& value) {
return ToStringHelper::BaseConvert<BASE_BITS>(value);
}

Expand Down Expand Up @@ -97,7 +118,7 @@ std::string COLD_NOINLINE SPrintFImpl( // NOLINT(runtime/string)
case 'i':
case 'u':
case 's':
ret += ToString(arg);
ret += ToStringOrStringView(arg);
break;
case 'o':
ret += ToBaseString<3>(arg);
Expand Down
2 changes: 2 additions & 0 deletions src/debug_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class Environment;

template <typename T>
inline std::string ToString(const T& value);
template <typename T>
inline auto ToStringOrStringView(const T& value);

// C++-style variant of sprintf()/fprintf() that:
// - Returns an std::string
Expand Down
Loading