[4.8p2] compile fails on class with non-default constructible member

My plugin fails to compile the “MyPluginName.generated.cpp” file.

In that file, the DEFINE_VTABLE_PTR_HELPER_CTOR(TClass) macro (related to hot relaods ?) adds:
TClass::TClass(FVTableHelper& Helper) : Super(Helper) {};

No class member is initialized, then:

  • members of a native type (int, etc.) are not initialized, (not a great idea)
  • members of a type that is not default constructable make the compilation fail

Is there an option to prevent the use of this macro for certain classes ?
(or all classes, as it looks quite dangerous…)

I get this error too. The following code is enough to trigger this. (at github 4.8 tip)

HEADER fail48.h:

#pragma once

#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

class MemberClass
{
public:
    MemberClass(int val) : m_val(val) {}
private:
    int m_val;
};

UCLASS()
class FAIL48_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	

	AMyActor();

private:
	
    MemberClass m_member;

};

SOURCE fail48.cpp:

#include "fail48.h"
#include "MyActor.h"

AMyActor::AMyActor()
 : Super(),
   m_member(2) // NOTE
{
}

In fail48.generated.cpp, the line

DEFINE_VTABLE_PTR_HELPER_CTOR(AMyActor);

Causes the following:

error C2512: 'MemberClass' : no appropriate default constructor available

The offending code is from CoreUObject/Public/UObject/ObjectBase.h:

#define DEFINE_VTABLE_PTR_HELPER_CTOR(TClass) \
	TClass::TClass(FVTableHelper& Helper) : Super(Helper) {};

This will never call any other ctor in TClass .

Tracing this further, it was implemented as a fix to UE-10111 Hot Reload crash with Scene Component tied to Actor class

The macro DEFINE_VTABLE_PTR_HELPER_CTOR is defined when WITH_HOT_RELOAD_CTORS is defined. As a temp workaround, I posted a separate question to find out how to disable WITH_HOT_RELOAD_CTORS .

EDIT Jun 15:
The 4.8 release notes (way down, in the Core section) say the following about this:

Hot reload uses special empty auto-generated constructors to obtain virtual table pointers from UObjects and to avoid re-constructing subobjects when creating temporary objects after loading the recompiled DLL but before the classes have been regenerated. This implies the requirement that all member variable types are default constructible.

The signature of the new constructor is UMyClass::UMyClass(FVTableHelper& Helper) and it can be manually defined in the header file to initialize all member variables that are not default-constructible

Auto-generation of the new constructors can be disabled by defining WITH_HOT_RELOAD_CTORS macro to 0 and setting [Core.System] UseVTableConstructors to False in BaseEngine.ini.

Note that disabling this feature may result in crashes when performing hot reload.

So it’s confirmed - either disable hot reload ctors or add this special ctor to your class members as needed.


The message of the commit which introduced this problem contains indications on how to workaround it:

Commit: 3c450b947746aec52557f1ea4c7546ab3f0204ca

Date: 2015-03-02 11:44:04

UE-10111: Hot Reload crash with Scene Component tied to Actor class

We’ve changed the way vtable ptr are obtained for UClasses. Right now we use special empty constructor to get it, so we don’t have to use normal one which was causing troubles. This special vtable helper constructor is generated automatically for most cases, but sometimes it’s not possible (e.g. no default constructor for members types). In such case there is a possibility to override that generated constructor and write a custom one. The signature is UCustomClass::UCustomClass(FVTableHelper& Helper) and it needs to call base class’es constructor with the same parameter. Please do not use these constructors for anything else. There is no guarantee the object will be in correct state after calling this.

You can still disable this functionality if something breaks, just set WITH_HOT_RELOAD_CTORS to 0.

[CL 2466152 by Jaroslaw Palczynski in Main branch]

So if I read the message correctly, my example above would be fixed by adding a ctor to AMyActor:

UCLASS()
class FAIL48_API AMyActor : public AActor
{
    GENERATED_BODY()
    	
public:	

    AMyActor();

    // adding this ctor fixes the problem:
    AMyActor(FVTableHelper& Helper)
    : Super(Helper),
      m_member(2) // and here you can initialize your members
   {
   }

private:
    	
    MemberClass m_member;
    
};

My engine is compiling, so right now I can’t confirm that doing this solves the problem.

[EDIT May 28: Just confirmed - adding the constructor fixes it.]

I’m not sure that I like the solution, but it works !
Thanks a lot !

Also, you could just make sure m_member type supports a default constructor.

not every class we want to construct does necessarily want a default constructor or is provided with one. In my case I use a third party library that has no default constructors for a specific reason.

I can confirm that adding the constructor mentioned above works for me too in my case.