Understanding FString::PrintLine

I’m trying to understand how the UCartridge::PrintLine instructions work.

From UCartridge.h, we have:

	void PrintLine(const FString& Line) const;
	void PrintLine(const TCHAR* Line) const; // Avoid template for this case.
	template<SIZE_T N, typename ...Types>
		void PrintLine(const FString& Line) const;
	void PrintLine(const TCHAR* Line) const; // Avoid template for this case.
	template<SIZE_T N, typename ...Types>
	void PrintLine(const TCHAR (&Fmt)[N], Types... Args) const
	{
		PrintLine(FString::Printf(Fmt, Args...));
	} const
	{
		PrintLine(FString::Printf(Fmt, Args...));
	}

Would someone please break these two lines and help me understand what is going on?

template<SIZE_T N, typename ...Types>
void PrintLine(const TCHAR (&Fmt)[N], Types... Args)

My guess is: N is the size of an array of TCHAR named Fmt passed as reference (&Fmt) . So we’re passing an array of TCHAR named Fmt with size N as a reference into our function. Is it?

What template <typename …Types> does?
What is Types… Args?

And why are we using TCHAR instead of just FString? I’m confused

Sure, though templates are definitely not beginner level stuff, so I wouldn’t worry about it if you’re still confused after.

That is correct, yes. That is the weird looking syntax to pass an array by reference. It uses a template parameter so it can work with any sized array that’s known at compile time

template<SIZE_T N>
void Something(const int32 (&A)[N])
{
    // use A
}

// using that template:
int32 Test1[3];
int32 Test2[5];

Something(Test1); // Deduces N to be 3. Instantiates the template Something<3>();
Something(Test1); // Deduces N to be 5. Instantiates the template Something<5>();

A string literal is just a character array. So

TEXT("Hello")

Would be of type

const TCHAR[6]

(6 due to the implicit null terminator.)

So hopefully putting all of that together explains the first parameter. It’s just passing the format string by reference.

That is a template parameter pack. It’s for a variable number of template parameters. Consider the following

PrintLine(TEXT("I'm %s,  and I'm %i years old", TEXT("Dan"), 29);
PrintLine(TEXT("%f is a cool number, %s"), 3.14f, TEXT("Bob");
PrintLine(TEXT("The answer to everything is %i ", 42);

Here PrintLine is called in 3 different ways

  1. With 2 format arguments, a string literal and an int.
  2. With 2 format arguments, a float and a string.
  3. With 1 format argument, an int.

And a variadic template is how you are able to express that.

The above would instantiate the following templates

// Calling code
PrintLine<30, const TCHAR*, int>(TEXT("I'm %s,  and I'm %i years old", TEXT("Dan"), 29);
// Generated function
void PrintLine(const TCHAR (&Fmt)[30], const TCHAR* Arg1, int32 Arg2) const
{
    PrintLine(FString::Printf(Fmt, Arg1, Arg2));
}

// Calling code
PrintLine<24, float, const TCHAR*>(TEXT("%f is a cool number, %s"), 3.14f, TEXT("Bob");
// Generated function
void PrintLine(const TCHAR (&Fmt)[24], float Arg1, const TCHAR* Arg2) const
{
    PrintLine(FString::Printf(Fmt, Arg1, Arg2));
}

// Calling code
PrintLine<31, int>(TEXT("The answer to everything is %i ", 42);
// Generated function
void PrintLine(const TCHAR (&Fmt)[31], int32 Arg1) const
{
    PrintLine(FString::Printf(Fmt, Arg1));
}

(It deduced const TCHAR* as arrays decay into pointers, which is why you need that weird syntax to pass by reference)

Because printf is a C function that only works with primitive types. FString::Printf uses a printf function to create an FString.

Got it, thank you!

I tought FString was a class, so isn’t it possible to just pass an FString object reference instead of that weird template + array reference sintax?

I was once a C++ developer, but modern C++ is so much harder than old C++, there are so many things to catch up. They are pushing the language away from mortal people lol.

Thank you for your answer

It is but FString::Printf requires that the format string is a string literal. There’s a static assert in its implementation that checks that. An FString or const TCHAR* can’t be used.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms