MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
FmtMacros.h File Reference

Use leading FMT_ or trailing _FMT fake text literals to create modern formatted strings with a better API. More...

#include <string>
#include "CoreMinimal.h"
#include "Mcro/Text.h"
#include "Mcro/TextMacros.h"
#include "Mcro/Enums.h"
#include "Mcro/Macros.h"

Go to the source code of this file.

Macros

#define MCRO_FMT_NAMED_ARG_TRANSFORM(s, data, elem)
 
#define MCRO_FMT_NAMED_ARG(key, value)
 
#define MCRO_FMT_NAMED(seq)
 
#define MCRO_FMT_NAMED_0(seq)
 
#define MCRO_FMT_ORDERED(...)
 
#define MCRO_FMT_ARGS(...)
 
#define FMT_(...)
 Leading fake text literal which makes using FString::Format(...); much more comfortable.
 
#define _FMT(...)
 Trailing fake text literal which makes using FString::Format(...); much more comfortable.
 
#define FMT_LOG(categoryName, verbosity, format, ...)
 Similar to UE_LOGFMT, but implemented via MCRO's own _FMT macro. So it's more convenient to pass format arguments.
 

Functions

template<size_t N>
FString operator% (FStringFormatOrderedArguments &&args, const TCHAR(&format)[N])
 
template<size_t N>
FString operator% (const TCHAR(&format)[N], FStringFormatOrderedArguments &&args)
 
template<size_t N>
FString operator% (FStringFormatNamedArguments &&args, const TCHAR(&format)[N])
 
template<size_t N>
FString operator% (const TCHAR(&format)[N], FStringFormatNamedArguments &&args)
 
FORCEINLINE FText operator% (FText const &format, FStringFormatOrderedArguments &&args)
 
FORCEINLINE FText operator% (FText const &format, FStringFormatNamedArguments &&args)
 

Detailed Description

Use leading FMT_ or trailing _FMT fake text literals to create modern formatted strings with a better API.

Author
David Mórász
Date
2025

The major difference from PRINTF_ or FString::Printf(...) is that FMT macros can take user defined string conversions into account, so more types can be used directly as arguments.

Todo
Make a unified way to handle format arguments for FText and FString. Currently _FMT on FText is using string conversions to do the actual formatting, and not vanilla FText::Format

Definition in file FmtMacros.h.

Macro Definition Documentation

◆ _FMT

#define _FMT ( ...)
Value:
% MCRO_FMT_ARGS(__VA_ARGS__)
#define MCRO_FMT_ARGS(...)
Definition FmtMacros.h:102

Trailing fake text literal which makes using FString::Format(...); much more comfortable.

FMT macros allow more types to be used directly in the format arguments expression because Mcro::Text has a couple of conversion utilities. If the first argument of _FMT is a sequence of ("key", value) pairs enclosed in parentheses, then named format arguments are assumed. Ordered format arguments are assumed otherwise. The two modes cannot be mixed.

Usage:

EPixelFormat format = PF_Unknown; int32 num = 42;
FString ordered = TEXT_"Hi {0}, your number is {1}" _FMT(format, num);
// -> "Hi PF_Unknown, your number is 42" ^ this space is important
// Named arguments look better with multiple lines on this version
FString named = TEXT_"Hi {Type}, your number is {Count}" _FMT(
(Type, format) // <- Notice the lack of comma here ^ this space is important
(Count, num)
);
// -> "Hi PF_Unknown, your number is 42"
#define _FMT(...)
Trailing fake text literal which makes using FString::Format(...); much more comfortable.
Definition FmtMacros.h:208
#define TEXT_
A convenience alternative to Unreal's own TEXT macro but this one doesn't require parenthesis around ...
Definition TextMacros.h:53

The following argument types are supported out-of-box:

  • Originally supported by FStringFormatArg and what's implicitly convertable to
    • FString, FStringView, int32, uint32, int64, uint64, float, double
    • ANSICHAR, WIDECHAR, UCS2CHAR, UTF8CHAR pointer strings
  • Anything which has a ToString() member method which produces one of the above type
    • Including but not exclusively FText and FName for example
  • STL strings and views of any encoding
  • Enums where their entries are serialized as human-readable names

This variant also allows to operate on FText instead of const TCHAR* strings if the fake string literal macro before _FMT yields FText. This version however still uses FString's under the hood, and it is not yet using vanilla FText::Format features

Remarks
To add more supported types specialize the TAsFormatArgument template functor for your preferred type and return a value which is implicitly convertible to FStringFormatArg in the Mcro::Text namespace. For example check Enums.h to see how that's done with enums. For your own types you can also implement a ToString() member method to get automatic support.
Warning
The named arguments overload (_FMT((A, a) (B, b) (C, c))) must not have comma , between the individual pairs. This is because named argument pairs are passed into this macro as a "sequence" instead of variadic arguments. Ordered format arguments however should be passed in as regular variadic arguments separated by comma , as nature intended.
Note
FMT macros are the only things in MCRO where excessive preprocessing is used

Definition at line 208 of file FmtMacros.h.

◆ FMT_

#define FMT_ ( ...)
Value:
MCRO_FMT_ARGS(__VA_ARGS__) % TEXT_

Leading fake text literal which makes using FString::Format(...); much more comfortable.

FMT macros allow more types to be used directly in the format arguments expression because Mcro::Text has a couple of conversion utilities. If the first argument of FMT_ is a sequence of ("key", value) pairs enclosed in parentheses, then named format arguments are assumed. Ordered format arguments are assumed otherwise. The two modes cannot be mixed.

Usage:

EPixelFormat format = PF_Unknown; int32 num = 42;
FString ordered = FMT_(format, num) "Hi {0}, your number is {1}";
// -> "Hi PF_Unknown, your number is 42"
// | Notice the lack of comma here
// V
FString named = FMT_((Type, format) (Count, num)) "Hi {Type}, your number is {Count}";
// -> "Hi PF_Unknown, your number is 42"
#define FMT_(...)
Leading fake text literal which makes using FString::Format(...); much more comfortable.
Definition FmtMacros.h:154

The following argument types are supported out-of-box:

  • Originally supported by FStringFormatArg and what's implicitly convertable to
    • FString, FStringView, int32, uint32, int64, uint64, float, double
    • ANSICHAR, WIDECHAR, UCS2CHAR, UTF8CHAR pointer strings
  • Anything which has a ToString() member method which produces one of the above type
    • Including but not exclusively FText and FName for example
  • STL strings and views of any encoding
  • Enums where their entries are serialized as human-readable names
Remarks
To add more supported types specialize the TAsFormatArgument template functor for your preferred type and return a value which is implicitly convertible to FStringFormatArg in the Mcro::Text namespace. For example check Enums.h to see how that's done with enums. For your own types you can also implement a ToString() member method to get automatic support.
Warning
The named arguments overload (FMT_((A, a) (B, b) (C, c))) must not have comma , between the individual pairs. This is because named argument pairs are passed into this macro as a "sequence" instead of variadic arguments. Ordered format arguments however should be passed in as regular variadic arguments separated by comma , as nature intended.
Note
FMT macros are the only things in MCRO where excessive preprocessing is used

Definition at line 154 of file FmtMacros.h.

◆ FMT_LOG

#define FMT_LOG ( categoryName,
verbosity,
format,
... )
Value:
UE_LOG(categoryName, verbosity, TEXT("%s"), *(TEXT(format) _FMT(__VA_ARGS__)))

Similar to UE_LOGFMT, but implemented via MCRO's own _FMT macro. So it's more convenient to pass format arguments.

This is naively implemented via regular UE_LOG which gets a single string format argument which is fed the result of the _FMT macro. UE_LOGFMT may have better performance or may have more insights to format arguments.

The same argument syntax applies here as with _FMT regarding the distinction between named and ordered arguments.

Named arguments:

// Vanilla:
UE_LOGFMT(LogSpaceMouseConfig, Display, "Input Binding {Context} / {Name} is handled",
cmd.GetBindingContext().ToString(),
cmd.GetCommandName().ToString()
);
// MCRO:
FMT_LOG(LogSpaceMouseConfig, Display, "Input Binding {Context} / {Name} is handled",
(Context, cmd.GetBindingContext()) // <- Notice the lack of comma here!
(Name, cmd.GetCommandName())
);
#define FMT_LOG(categoryName, verbosity, format,...)
Similar to UE_LOGFMT, but implemented via MCRO's own _FMT macro. So it's more convenient to pass form...
Definition FmtMacros.h:246

Ordered arguments:

// Vanilla:
UE_LOGFMT(LogSpaceMouseConfig, Display, "Input Binding {0} / {1} is handled",
cmd.GetBindingContext().ToString(),
cmd.GetCommandName().ToString()
);
// MCRO:
FMT_LOG(LogSpaceMouseConfig, Display, "Input Binding {0} / {1} is handled",
cmd.GetBindingContext(),
cmd.GetCommandName()
);

Definition at line 246 of file FmtMacros.h.

◆ MCRO_FMT_ARGS

#define MCRO_FMT_ARGS ( ...)
Value:
BOOST_PP_IIF(BOOST_PP_IS_BEGIN_PARENS(__VA_ARGS__), \
MCRO_FMT_NAMED(BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)), \
MCRO_FMT_ORDERED(__VA_ARGS__) \
)
#define MCRO_FMT_ORDERED(...)
Definition FmtMacros.h:100
#define MCRO_FMT_NAMED(seq)
Definition FmtMacros.h:84

Definition at line 102 of file FmtMacros.h.

◆ MCRO_FMT_NAMED

#define MCRO_FMT_NAMED ( seq)
Value:
BOOST_PP_IIF(BOOST_PP_IS_BEGIN_PARENS(seq), \
BOOST_PP_IDENTITY_N(, 1) \
)(seq)
#define MCRO_FMT_NAMED_0(seq)
Definition FmtMacros.h:90

Definition at line 84 of file FmtMacros.h.

◆ MCRO_FMT_NAMED_0

#define MCRO_FMT_NAMED_0 ( seq)
Value:
BOOST_PP_SEQ_ENUM( \
BOOST_PP_SEQ_TRANSFORM( \
BOOST_PP_VARIADIC_SEQ_TO_SEQ(seq) \
) \
) \
)
#define MCRO_FMT_NAMED_ARG_TRANSFORM(s, data, elem)
Definition FmtMacros.h:81
FStringFormatNamedArguments NamedArguments(TTuple< FString, Args >... args)
Create a named argument list for a string format from input argument tuples.
Definition Text.h:444

Definition at line 90 of file FmtMacros.h.

◆ MCRO_FMT_NAMED_ARG

#define MCRO_FMT_NAMED_ARG ( key,
value )
Value:
MakeTuple(FString(TEXT(#key)), value)

Definition at line 82 of file FmtMacros.h.

◆ MCRO_FMT_NAMED_ARG_TRANSFORM

#define MCRO_FMT_NAMED_ARG_TRANSFORM ( s,
data,
elem )
Value:
BOOST_PP_EXPAND(MCRO_FMT_NAMED_ARG elem)
#define MCRO_FMT_NAMED_ARG(key, value)
Definition FmtMacros.h:82

Definition at line 81 of file FmtMacros.h.

◆ MCRO_FMT_ORDERED

#define MCRO_FMT_ORDERED ( ...)
Value:
FStringFormatOrderedArguments OrderedArguments(Args &&... args)
Create an ordered argument list for a string format from input arguments.
Definition Text.h:432

Definition at line 100 of file FmtMacros.h.

Function Documentation

◆ operator%() [1/6]

template<size_t N>
FString operator% ( const TCHAR(&) format[N],
FStringFormatNamedArguments && args )

Definition at line 60 of file FmtMacros.h.

◆ operator%() [2/6]

template<size_t N>
FString operator% ( const TCHAR(&) format[N],
FStringFormatOrderedArguments && args )

Definition at line 44 of file FmtMacros.h.

◆ operator%() [3/6]

template<size_t N>
FString operator% ( FStringFormatNamedArguments && args,
const TCHAR(&) format[N] )

Definition at line 52 of file FmtMacros.h.

◆ operator%() [4/6]

template<size_t N>
FString operator% ( FStringFormatOrderedArguments && args,
const TCHAR(&) format[N] )

Definition at line 36 of file FmtMacros.h.

◆ operator%() [5/6]

FORCEINLINE FText operator% ( FText const & format,
FStringFormatNamedArguments && args )

Definition at line 74 of file FmtMacros.h.

◆ operator%() [6/6]

FORCEINLINE FText operator% ( FText const & format,
FStringFormatOrderedArguments && args )

Definition at line 67 of file FmtMacros.h.