UEC++帶參數委托用委托模闆傳遞參數
- 前言
- 放出代碼
- 總結
前言
之前為了實作一個類似Unity裡面DoTween.To的功能,想在參數Tween的過程中将參數更新給委托,實作Tween的過程中委托也執行并傳該參數值,為此設計了DECLARE_DELEGATE_OneParam帶一個參數的三種委托,分别為了傳遞float、FVector、FRotator類型的參數,但到最後SetTimer更新模闆方法的時候,缺發現委托并不能像之前定義的T模闆類型一樣傳遞,為此調研下了下才知道委托也可以用作模闆參數,這樣我們就将傳入的委托類型也設定為模闆的形參,在模闆展開後,委托調用的時候類型是比對的就能編譯過。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicWZwpmLldTN5QGOlhDZmJWN4IGN4UGM0QTOxMGZiFmZ3gDOwMzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpeg)
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引用捕獲一個局部變量,但兩個方法都會把這個問題搞複雜。