【UE4/Unreal C++】std::function の代わりに使えるTFunction型

2023年2月28日

概要

C++には関数オブジェクトを引数などで渡すことができる std::function があります。
これをUnreal C++ で実現する場合は TFunction型が使えます。

通常、差し替え可能な処理(関数)を渡したい場合、ブループリントならデリゲートで実現する事ができます。
Unreal C++ にもデリゲートがありますが、デリゲートのオブジェクトを宣言する必要があったり実装はやや手間です。

外部に公開する必要が無いし、ちょっとした処理の置き換えをしたい場合(例えばBP毎の設定処理を C++側で手軽に書き分けたい時)などに重宝します。

TFunction

定義

Function.h
template
class TFunction final : public UE4Function_Private::TFunctionRefBase, FuncType>

記法

TFunction<戻り値の型 (引数の型, …)>

簡単な使い方はヘッダーファイルのコメントに書かれていました。

Function.hから抜粋

// Something.h
TFunction<FString (int32)> GetTransform();

// Something.cpp
TFunction<FString (int32)> GetTransform(const FString& Prefix)
{
     // Squares number and returns it as a string with the specified prefix
    return [=](int32 Num) {
        return Prefix + TEXT(": ") + TTypeToString<int32>::ToString(Num * Num);
    };
}

// SomewhereElse.cpp
#include "Something.h"

void Func()
{
    TFunction<FString (int32)> Transform = GetTransform(TEXT("Hello"));
    FString Result = Transform(5); // "Hello: 25"
}

他の使用例

ちょっと微妙かもしれませんが、使用例を書いてみました。

hoge.h
template<class T = UUserWidget>
void CreateWidgetTemplate(
	TSubclassOf<UUserWidget> ClassType,
	int32 WidgetNum,
	TFunction<void(T*)> WidgetInitializer ) const
{
	for (int32 i = 0; i < WidgetNum; ++i)
	{
		const auto Widget = CreateWidget<T>(GetWorld(), ClassType);
		if (Widget)
		{
			//
			// 何か共通の処理
			//

			//
			// クラス個別の処理
			//
			WidgetInitializer(Widget);
		}
	}
}

hoge.cpp
void Initialize()
{
	//ウィジェットをまとめて作る
	CreateWidgetTemplate<UWidgetClassA>(ClassTypeA, 16, [](UWidgetClassA* Widget)
		{
			if (Widget)
			{
				Widget->FuncA();
			}
		});

	CreateWidgetTemplate<UWidgetClassB>(ClassTypeB, 8, [](UWidgetClassB* Widget)
		{
			if (Widget)
			{
				Widget->FuncB();
			}
		});
}