Generic function in parameter?

Hi

I’m trying to make a component which could be able to handle the time generally. (It’s like regrouping some useful function with FTimerHandle and FTimeManager in the same Class)

But actually i’m trying to create the same kind of SetTimer (just to set a timer) and i’m stuck trying to pass a generic function in param… Like Amyactor::Myfunction()

This is my Timer.h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once
#include "Timer.generated.h"

/**
*
*/
UCLASS()
class RAPIERE_API UTimer : public UActorComponent
{
	GENERATED_BODY()
public:
	UTimer();
	void InitComponent(UWorld* & world, FTimerHandle & Handler);
	template<class T1>
	void SetTimer(float value, typename FTimerDelegate::TUObjectMethodDelegate< T1 >::FMethodPtr, bool loop = true);
	~UTimer();
	// Called when the game starts
	virtual void BeginPlay() override;

	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
	UPROPERTY(VisibleAnywhere, category = Timer)
		bool bTimerExpired;
protected:

	/**Object handling the timer*/
	UPROPERTY(VisibleAnywhere, category = Timer)
		FTimerHandle SampleTimerHandle;
	/**The world passed by the Actor (mainly by GetWorld() )*/
	UPROPERTY(VisibleAnywhere, category = Timer)
		UWorld* World;
	/**Check if the timer has expired (true if expire*/
	

};

And this is my .cpp for settimer:

template<class T1>
void UTimer::SetTimer(float value, typename FTimerDelegate::TUObjectMethodDelegate< T1 >::FMethodPtr, bool loop)
{
	if (World)
	{
		// If the timer has expired or does not exist, start it    
		World->GetTimerManager().ClearTimer(SampleTimerHandle);
		World->GetTimerManager().SetTimer(SampleTimerHandle, this, InTimerMethod, value);
		bTimerExpired = false;
	}
}

Am i wrong somewhere with the template?
Thanks in advance

Hey,

I think you have to define your templated function in you header file.

Can you provide the compiler errors?

Greetings

Hi
Thanks for your reply,
The error i have when i use the function is :

Error C_Player.cpp.obj : error LNK2019: unresolved external symbol "public: void __cdecl UTimer::SetTimer<class AC_Player>(float,void (__cdecl AC_Player::*)(void),bool)" (??$SetTimer@VAC_Player@@@UTimer@@QEAAXMP8AC_Player@@EAAXXZ_N@Z) referenced in function "public: virtual void __cdecl AC_Player::Tick(float)" (?Tick@AC_Player@@UEAAXM@Z)

And if i try to change the method signature, i generally get a cannot convert … to

Hey
can you show me how you call SetTimer??

I initialize the timer in the constructor:

Jump_Timer = CreateDefaultSubobject<UTimer>(TEXT("Timer"));
	UWorld * world= GetWorld();
	FTimerHandle handle = FTimerHandle();
	Jump_Timer->InitComponent(world, handle);

And I use the function here

Jump_Timer->SetTimer<AC_Player>(1000.f, &AC_Player::StopJump,true);

You don’t have to specifiy the <> template class because you use &AC_Player which automatically specifies the class.
use Jump_Timer->SetTimer(1000.f, &AC_Player::StopJump, true);

If this isn’t the error:
Can you show me the StopJump Method??

If i remove the <> template class, i get this message:

Error	C2672	'UTimer::SetTimer': no matching overloaded function found
Error	C2783	'void UTimer::SetTimer(float,TBaseDelegate<void>::TBaseDelegate<TTypeWrapper<void>>::TUObjectMethodDelegate<UserClass>::FMethodPtr,bool)': could not deduce template argument for 'T1'

I have to remove something from the ;h too?

The stopjump function .H:

void StopJump();

And the .cpp:

void AC_Player::StopJump()
{
	BisJumping = false;
}

Hmm.
Did you define your templated function in the header file of UTimer??
Unfortunately I cannot test it myself at the moment :confused:

With this, it’s not define correctly?

template<class T1>
     void SetTimer(float value, typename FTimerDelegate::TUObjectMethodDelegate< T1 >::FMethodPtr, bool loop = true);

Ok I got my hands on an Unreal Computer :smiley:

So my attempt was like followed:

//UTimer .h
template<class T1>
	void UTimer::SetTimer(float value, T1* Object, typename FTimerDelegate::TUObjectMethodDelegate< T1 >::FMethodPtr InTimerMethod, bool loop)
	{
		if (World)
		{
			// If the timer has expired or does not exist, start it    
			World->GetTimerManager().ClearTimer(SampleTimerHandle);
                        //TimerManager needs an UObject, so we give him instead of "this" 
                        //the T1 Object
			World->GetTimerManager().SetTimer(SampleTimerHandle, Object, InTimerMethod, value);
			bTimerExpired = false;
		}
	}

In our Player we call the Method like followed:

Timer->SetTimer(1000, this, &AC_Player::StopJump, true);

Cheers :slight_smile:

Thanks for your time dude, seems to work :slight_smile:

Nice I’m glad I could help you :slight_smile:
Could you Accept my answer so that everyone can see that this is question was answered?

Thx :wink:
Have a nice weekend

Greetings