天天看点

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引用捕获一个局部变量,但两个方法都会把这个问题搞复杂。

继续阅读