GENERATED_BODY() causing function declaration and member inaccessibility errors

The errors are not in the definition of these two. The error occurs when I use these methods in other classes. I have another class called UCSpecies which contains a UCGenome object as a member variable. So in various constructors and methods of UCSpecies, I am using the copy constructor and assignment operator of UCGenome to set the value of that member. That’s where the errors are thrown.

UCSpecies::UCSpecies(UCGenome &FirstOrg,
int SpeciesID) :m_iSpeciesID(SpeciesID),
m_fBestFitness(FirstOrg.Fitness()),
m_iGensNoImprovement(0),
m_iAge(0),
m_Leader(FirstOrg), //copy constructor error
m_fSpawnsRqd(0)
{
m_vecMembers.Add(&FirstOrg);
m_Leader = FirstOrg; //assignment operator error
}

void UCSpecies::AddMember(UCGenome &NewMember)
{
	if (NewMember.Fitness() > m_fBestFitness)
	{
		m_fBestFitness = NewMember.Fitness();
		m_iGensNoImprovement = 0;
		m_Leader = NewMember; //assignment operator error
	}

	m_vecMembers.Add(&NewMember);
}

UCGenome UCSpecies::Spawn()
{
	UCGenome baby;

	if (m_vecMembers.Num() == 1)
	{
		baby = *m_vecMembers[0]; //assignment operator error
	}
	else
	{
		int MaxIndexSize = (int)(UCParams::fSurvivalRate * m_vecMembers.Num()) + 1;
		int TheOne = RandomInt(0, MaxIndexSize);
		baby = *m_vecMembers[TheOne]; //assignment operator error
	}

	return baby; //copy constructor error
}

It is assuming the copy constructor and the assignment operator to be private members which is probably why it is unable to access them. But a constructor should obviously be a public member right?

Oh yeah that is the problem. So I told you about custom lifecycle management in ue4 earlier. This is part of it. Since you don’t use new and delete in unreal, the constructors are not public. You use methods like NewObject and such to instantiate new stuff. It has to do with memory management, unreal allocates memory on its own instead of using the standard C++ way. It makes memory allocation way faster.

So no, you can’t simply call the constructor. It gets called by NewObject and similar methods. Check this out for further information and a workaround.

So I basically need to change the way I am defining the copy constructor as well as its usage. I am unable to understand the parameters of the copy constructor declaration provided in the link. Could you kindly explain how that syntax applies to my case?

The function in which I want to call the copy constructor has the template passed as a parameter by reference. Would that cause problems?

First of all: you can find the definition of NewObject in UObjectGloabs.h:1221 this is its full signature:

    T* NewObject(UObject* Outer, UClass* Class, FName Name = NAME_None, EObjectFlags Flags = RF_NoFlags, UObject* Template = nullptr, bool bCopyTransientsFromClassDefaults = false, FObjectInstancingGraph* InInstanceGraph = nullptr)

So the signature works as follows:

  • Outer: the outer object can be any object. It is used to determine the lifecycle and how it will be saved, to my knowledge.
    (If you created a component you would probably use the actor that the component should stick to as the outer)
  • Class: this is used to spawn blueprint classes. If you just use a c++ class, you can just use YourClass::StaticClass() as this argument.
  • Name: is simply the name it will have. This will be the name you will see when inspecting it in the world outliner for example. you don’t have to name it
  • Flags: The definition reveals that this is some very low level stuff. I never used this.
  • Template: This is the object that you want to copy construct from
  • bCopyTransientsFromClassDefaults: No idea
  • InInstanceGraph: No Idea

The baseline is: all the “No Ideas” have default values, so just use those default values.

I posted my comment as a new anser, since this comment tree is getting rather annoying to read (its so small now).

no. You would simply use the & operator to get the adress of the reference.I would encourage you to just try it and see if you get any errors. You can just substitute one call at a time and see what happens.

This is what I tried:

		m_Leader = NewObject(this, UCGenome::StaticClass(), NAME_None, RF_NoFlags, NewMember, false, nullptr);

And the errors I get are this:

2>C:\Users\Documents\Unreal Projects\Source\CSpecies.cpp(40): error C2672: ‘NewObject’: no matching overloaded function found
2>C:\Users\Documents\Unreal Projects\Source\CSpecies.cpp(40): error C2780: ‘T *NewObject(UObject *,FName,EObjectFlags,UObject *,bool,FObjectInstancingGraph *)’: expects 6 arguments - 7 provided
2> c:\program files\epic games\ue_4.15\engine\source\runtime\coreuobject\public\UObject/UObjectGlobals.h(1250): note: see declaration of ‘NewObject’
2>C:\Users\Documents\Unreal Projects\Source\CSpecies.cpp(40): error C2780: ‘T *NewObject(UObject *)’: expects 1 arguments - 7 provided
2> c:\program files\epic games\ue_4.15\engine\source\runtime\coreuobject\public\UObject/UObjectGlobals.h(1239): note: see declaration of ‘NewObject’
2>C:\Users\Documents\Unreal Projects\Source\CSpecies.cpp(40): error C2783: ‘T *NewObject(UObject *,UClass *,FName,EObjectFlags,UObject *,bool,FObjectInstancingGraph *)’: could not deduce template argument for ‘T’
2> c:\program files\epic games\ue_4.15\engine\source\runtime\coreuobject\public\UObject/UObjectGlobals.h(1221): note: see declaration of ‘NewObject’

I tried this:

		m_Leader = NewObject<UCGenome>(&NewMember);

And the error I get now is that it is unable to recognize the ‘=’ operator. I believe NewObject() returns a pointer to the object? From the compile log I can see that that’s causing the error as it is not able to do UCGenome = UCGenome*. m_Leader is a UCGenome and NewObject returns UCGenome*.

I did this:

		m_Leader = *(NewObject<UCGenome>(&NewMember));

I had to add the because otherwise it was giving error that it is unable to deduce the type. But now it goes back to the initial error of operator ‘=’ being inaccessible. I have commented out the declaration of the operator in the .h file but it is still giving this error.

I apologize for asking basic questions. Please bear with me.

I suspect NewMember is your reference? You would have to use the & operator to get the adress to that, so try using &NewMember in the function call.

try
m_Leader = *(NewObject < UCGenome>(&NewMember))

We are getting into really basic stuff here, I think you should read some tutorials on C++ pointers and type conversion.

The convention is to use pointers instead of references. This is very broadly spoken, and there are of course applications for references, but you should probably use a pointer as the argument to you method here, instead of the reference you currently have. I am a bit supprised that I didn’t ran into this myself yet. I find that references are usually used for data objects, but all the UObject derived classes are usually referenced by pointers. I would advise you to read a tutorial about them like this for example. I will not post the fix here, because you will easily be able to do it yourself once you are through that tutorial, and you definitely should know about pointers when you want to use C++ in UE. If you are done with that and still have questions you can of course ask again.