天天看點

UEC++帶參數委托用委托模闆傳遞參數前言放出代碼總結

UEC++帶參數委托用委托模闆傳遞參數

  • 前言
  • 放出代碼
  • 總結

前言

之前為了實作一個類似Unity裡面DoTween.To的功能,想在參數Tween的過程中将參數更新給委托,實作Tween的過程中委托也執行并傳該參數值,為此設計了DECLARE_DELEGATE_OneParam帶一個參數的三種委托,分别為了傳遞float、FVector、FRotator類型的參數,但到最後SetTimer更新模闆方法的時候,缺發現委托并不能像之前定義的T模闆類型一樣傳遞,為此調研下了下才知道委托也可以用作模闆參數,這樣我們就将傳入的委托類型也設定為模闆的形參,在模闆展開後,委托調用的時候類型是比對的就能編譯過。

UEC++帶參數委托用委托模闆傳遞參數前言放出代碼總結
DECLARE_DELEGATE_OneParam(FFloatDelegate, float);
DECLARE_DELEGATE_OneParam(FFVectorDelegate, FVector);
DECLARE_DELEGATE_OneParam(FRotatorDelegate, FRotator);

template<typename TDelegateOneParam,typename T>
void TEST(TDelegateOneParam delegateOneParam, T var) {
	if (delegateOneParam.IsBound()) {
		delegateOneParam.Execute(var);
	}
}
           

放出代碼

#include "DelegateTemplateDistribution.h"
#include <Kismet\KismetSystemLibrary.h>

DECLARE_DELEGATE_OneParam(FFloatDelegate, float);
DECLARE_DELEGATE_OneParam(FFVectorDelegate, FVector);
DECLARE_DELEGATE_OneParam(FRotatorDelegate, FRotator);

template<typename TDelegateOneParam,typename T>
void TEST(TDelegateOneParam delegateOneParam, T var) {
	if (delegateOneParam.IsBound()) {
		delegateOneParam.Execute(var);
	}
}

// Sets default values
ADelegateTemplateDistribution::ADelegateTemplateDistribution()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = false;

}

// Called when the game starts or when spawned
void ADelegateTemplateDistribution::BeginPlay()
{
	Super::BeginPlay();
		
	FFloatDelegate floatDelegate;	
	floatDelegate.BindUObject(this,&ADelegateTemplateDistribution::FTest);
	TEST(floatDelegate,100.0);

	FFVectorDelegate vectorDelegate;
	TEST(vectorDelegate, FVector::ZeroVector);

	FRotatorDelegate rotatorDelegate;
	TEST(rotatorDelegate, FRotator::ZeroRotator);
}

// Called every frame
void ADelegateTemplateDistribution::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ADelegateTemplateDistribution::FTest(float f) {
	UKismetSystemLibrary::PrintString(GWorld, FString::Printf(TEXT("FTest	f = %f"), f));
}
           

總結

c++模闆是編譯的時候展開,既然委托傳參數量是固定的,加模闆參數實際上就是讓編譯器生成了三個版本的函數,分别對應三種不同類型的委托。隻是無法确定參數類型和對應的委托類型,但是隻要比對那展開的代碼就能編譯過,否則就編譯報錯。

這是一個非常典型的靜态泛型運用場合,讓委托類型也作為一個單獨的模闆形參,就像一個宏展開一樣,否則就隻能傳無參數的委托,要麼計算結果得存在外部的成員變量,要麼就要用lamba引用捕獲一個局部變量,但兩個方法都會把這個問題搞複雜。

繼續閱讀