#std::vformat Logging + AZERTY conveniences
1 messages · Page 1 of 1 (latest)
@subtle jackal Improved with error catching on bad formats (no crash now 😄 ). Also this way exposes both styles so you can type AZERTY style or copy and paste standard style and just use the correct macro.
LOG(LogTemp, Warning, "{}", 42); // "42"
AZERTY_LOG(LogTemp, Warning, "§%", 42); // "42"
/**
* Swaps brace characters for a std::format string.
* Used to make it easier to type format strings on non-QWERTY keyboards.
* Brace characters will swap to their substitute so that they are still available.
*
* FString Format = TEXT("§% {}");
* FString ActualFormat = SwapFormatBraces(Format, L'§', L'%'); // "{} §%"
*
* @param Format std::format string
* @param LeftBraceSubstitute Substitute for { in format
* @param RightBraceSubstitute Substitute for } in format
* @return Swapped std::format string
*/
inline FString SwapFormatBraces(const FString& Format, const FString::ElementType LeftBraceSubstitute, const FString::ElementType RightBraceSubstitute)
{
FString Result = Format;
for(int32 i=0; i < Result.Len(); ++i)
{
if(LeftBraceSubstitute == Result[i]) {
Result[i] = '{';
}
else if(RightBraceSubstitute == Result[i]) {
Result[i] = '}';
}
else if('{' == Result[i]) {
Result[i] = LeftBraceSubstitute;
}
else if('}' == Result[i]) {
Result[i] = RightBraceSubstitute;
}
}
return Result;
}
/**
* Formats a string using std::vformat
*
* FString Format = TEXT("{}");
* FString Formatted = FormatString(Format, 42); // "42"
*
* @param Format std::format string
* @param Args Arguments
* @return Formatted string
*/
template <typename ... TArgs>
FString FormatString(const FString& Format, TArgs... Args)
{
try
{
return std::vformat(*Format, std::make_wformat_args(Args...)).c_str();
}
catch(std::format_error& FormatError)
{
return FString::Printf(TEXT("String Format Error: %s \"%s\""), *FString(FormatError.what()), *Format);
}
}
/**
* Formats a string using SwapFormatBraces and std::vformat
*
* FString Format = TEXT("§%");
* FString Formatted = FormatString_UsingSwappedFormatBraces(Format, L'§', L'%', 42); // "42"
*
* @param Format std::format string
* @param LeftBraceSubstitute Substitute for { in format
* @param RightBraceSubstitute Substitute for } in format
* @param Args Arguments
* @return Formatted string
*/
template <typename ... TArgs>
FString FormatString_UsingSwappedFormatBraces(const FString& Format, const FString::ElementType LeftBraceSubstitute, const FString::ElementType RightBraceSubstitute, TArgs... Args)
{
const FString ActualFormat = SwapFormatBraces(Format, LeftBraceSubstitute, RightBraceSubstitute);
try
{
return std::vformat(*ActualFormat, std::make_wformat_args(Args...)).c_str();
}
catch(std::format_error& FormatError)
{
return FString::Printf(TEXT("String Format Error: %s \"%s\" -> \"%s\""), *FString(FormatError.what()), *Format, *ActualFormat);
}
}
/**
* Log using std::vformat
*
* LOG(LogTemp, Warning, "{}", 42); // "42"
*/
#define LOG(CATEGORY, VERBOSITY, FORMAT, ...) UE_LOG(CATEGORY, VERBOSITY, TEXT("%s"), *FormatString(TEXT(FORMAT), ##__VA_ARGS__))
/**
* Log using std::vformat and substitute braces for AZERTY keyboards
*
* AZERTY_LOG(LogTemp, Warning, "§%", 42); // "42"
*/
#define AZERTY_LOG(CATEGORY, VERBOSITY, FORMAT, ...) UE_LOG(CATEGORY, VERBOSITY, TEXT("%s"), *FormatString_UsingSwappedFormatBraces(TEXT(FORMAT), L'§', L'%', ##__VA_ARGS__))

@steady pilot for some reasons i cant use strings as the args
0>format(3417): Error C2338 : static_assert failed: 'Cannot format an argument. To make type T formattable, provide a formatter<T> specialization. See N4928 [format.arg.store]/2 and [formatter.requirements].'
and
0>format(1782): Error C2665 : 'std::_Format_arg_traits<_Context>::_Phony_basic_format_arg_constructor': no overloaded function could convert all the argument types
showing errors is great but how come you never show me what you're doing?
anyway this should work fine
FString TestString = TEXT("Test");
LOG(LogTemp, Warning, "{}", *TestString); // "Test"
AZERTY_LOG(LogTemp, Warning, "§%", *TestString); // "Test"
so
LOG(LogTemp, Warning, "{}", "some text" );
cant work ?
of course it can't
sometimes i want to do a ternary with a string
but also why would you do that
ig ill make a var
just put it in the format
if it's static text like that
but anyway
LOG(LogTemp, Warning, "{}", TEXT("some text"));
might work lemme check
ill try later
yeh this works
you just need the TEXT macro if you're gonna put in fixed text
this works but this doesnt
// works
SL_INDVLOG("Inventory component slot change delegate got fired. Index: §%, Item Tag: §%", Index, Item ? 10 : 10);
// compile error
SL_INDVLOG("Inventory component slot change delegate got fired. Index: §%, Item Tag: §%", Index, Item ? Item->GetDebugName() : TEXT("Null"));
// or
const FString& Temp = "Null";
SL_INDVLOG("Inventory component slot change delegate got fired. Index: §%, Item Tag: §%", Index, Item ? Item->GetDebugName() : Temp);
@steady pilot
#define SL_INDVLOG(FORMAT, ...) SL_LOG(LogLSInventorySystem, Display, GetWorld(), FORMAT, ##__VA_ARGS__)
and SL_LOG is
#define SL_SLOG(CATEGORY, VERBOSITY, FORMAT, ...) UE_LOG(CATEGORY, VERBOSITY, TEXT("%s %s"), __FUNCTIONW__, *FormatString_UsingSwappedFormatBraces(TEXT(FORMAT), L'§', L'%', ##__VA_ARGS__))
you need to "deref" the string
SL_INDVLOG("Inventory component slot change delegate got fired. Index: §%, Item Tag: §%", Index, Item ? *Item->GetDebugName() : TEXT("Null"));
assuming FString GetDebugName()
np
we can expand this log system like Laura did to do some of this automatically for you
I'll help you with that later though
i can type a * im not that lazy