How to Use Nested Delegate Types (C++)

The Engine Example

There are few places in the Engine where the developers use nested delegates (i.e. they are declared inside another class). The ones I have used most commonly are those contained in FWorldDelegates.

This is what the header file, World.h, looks like for those delegates.

/** World delegates */
class ENGINE_API FWorldDelegates
{
public:
	DECLARE_MULTICAST_DELEGATE_TwoParams(FWorldInitializationEvent, UWorld* /*World*/, const UWorld::InitializationValues /*IVS*/);

// ...more delegates declared here...

// Callback for world initialization (pre) // public static delegate exposed
static FWorldInitializationEvent OnPreWorldInitialization;

I have identified 3 distinct elements in the FWorldDelegates:

  • The MODULE_API macro in the class declaration (i.e. ENGINE_API)
  • A public nested delegate type declaration (i.e. DECLARE_MULTICAST_DELEGATE…)
  • A public and static delegate declaration (i.e. static FWorldInitializationEvent…)

If I try to bind a function to an FWorldDelegates, as below, it compiles fine.

#include "Engine/World.h"

FWorldDelegates::AddUObject(this, &MyBindingClass:MyBindingFunction);

The Problem

I am trying to do an identical thing: create a shell class with nested delegate declarations and static delegates, and bind to those delegates.

The declaration compiles fine. However, when I try to bind to one of my custom delegates, I get a linker error for an unresolved symbol:

1>Module.Remapt.cpp.obj : error LNK2001: unresolved external symbol "public: static class TMulticastDelegate<void> FRemaptDelegates::NotifyRemaptEvent" (?NotifyRemaptEvent@FRemaptDelegates@@2V?$TMulticastDelegate@X$$V@@A)

Note: The binding function/class is in the same module as the static delegates. As far as I can tell, I have copied the FWorldDelegates implementation exactly.

So how can I get this to compile?

As usual, resolved it just after posting the question…

Define the Static Delegate Members in a Source File (.cpp)

This is a cpp issue more than a UE4 issue, as described in this post. Static class members have to be defined after being declared.

The declaration of the delegate is covered here, in our header file (.h):

class FDelegateHolderClass
{
    // ...
    DECLARE_MULTICAST_DELEGATE(FGenericDelegate)
    static FGenericDelegate MyDelegate;
    // ...
}

Now you just have to define the delegate here, in our source file (.cpp):

// Somewhere inside a source file, outside of any functions/scopes
FDelegateHolderClass::FGenericDelegate FDelegateHolderClass::MyDelegate;

Et voila! It works perfectly!