DECLARE_DELEGATE_OneParam makes compile error on param being a TMap

The line:

DECLARE_DELEGATE_OneParam(SetArmorDelegate, TMap<int, FString>)

causes the compile error:

error C4002: too many actual parameters for macro 'DECLARE_DELEGATE_OneParam'
error C2976: 'TMap': too few template arguments
error C2146: syntax error: missing '>' before identifier 'SetArmorDelegate'
error C2143: syntax error: missing '>' before ';'
error C3203: 'TMap': unspecialized class template can't be used as a template argument for template parameter error C2208: 'TBaseDelegate<void,int32>': no members defined using this type
error C4002: too many actual parameters for macro 'DECLARE_DELEGATE_OneParam'
error C2976: 'TMap': too few template arguments
note: see declaration of 'TMap'
error C2146: syntax error: missing '>' before identifier 'SetArmorDelegate'
error C2143: syntax error: missing '>' before ';'
error C3203: 'TMap': unspecialized class template can't be used as a template argument for template parameter 'ParamTypes', expected a real type
error C2208: 'TBaseDelegate<void,int32>': no members defined using this type

Every error being on the same line. However, when I change this line to:

DECLARE_DELEGATE_OneParam(SetArmorDelegate, TArray<int>)

No compile errors.

Additional information:

The line that causes the error is declared inside a class (A UActorComponent, but I don’t think that matters), after GENERATED_BODY(). Both declaring the delegate inside of “private” and outside cause the same errors i.e:

class API myclass : public UActorComponent
{
	GENERATED_BODY()

	DECLARE_DELEGATE_OneParam(SetArmorDelegate, TMap<int, FString>)
...

and

class API myclass : public UActorComponent
{
	GENERATED_BODY()
private:
	DECLARE_DELEGATE_OneParam(SetArmorDelegate, TMap<int, FString>)
...

Cause the same error.

Hi,

Mixing macros and multi-argument templates in C++ don’t work so well, because the commas in the template are parsed as part of the macro instead:

First arg: SetArmorDelegate
Second arg: TMap<int
Third arg: FString>

For native code, you should use a typedef instead:

typedef TMap<int, FString> FMyMapType;
DECLARE_DELEGATE_OneParam(SetArmorDelegate, FMyMapType)

For UHT, the only workaround I would suggest is to wrap it up in a USTRUCT:

USTRUCT()
struct FMyTypeContainingAMap
{
    TMap<int, FString> Map;
};

DECLARE_DELEGATE_OneParam(SetArmorDelegate, FMyTypeContainingAMap)

Hope this helps,

Steve

1 Like

ah I had a sneaking suspicion that was the problem. Really quick though, do typedefs replicate?

In native code, a typedef acts as if you had typed the actual type there, so replication should be unaffected.

In reflected code (UCLASS etc.), typedefs are not supported - that’s why you need the USTRUCT() method I suggested above. And USTRUCTs replicate.

Steve