How do I resolve "Error: 'TSharedRef' : no appropriate default constructor available?"

Hello,

I have added this line of code in a plugin module class:

TSharedRef< FToolBarExtension > ToolbarExtension;

And it’s throwing this error:

Error 1 error C2512: ‘TSharedRef<FToolBarExtension,0>’ : no appropriate default constructor available d:\000-myprojects\ue4\unrealengine\engine\plugins\hamadsplugin\source\hamadsplugin\private\HamadsPlugin.h 45 1 UE4

I’m not sure why it needs a constructor and how can I do that?

Thanks!

You’re probably trying to assign something to it that it can’t handle.

Can we see the code that’s using TSharedRef? That will help work out what’s wrong.

For my learning purposes, I wanted to do a plugin that extends the editor by adding a button in the toolbar and when clicked it simply displays a log message. All is working fine. It was recommended that I remove the extension when ShutdownModule(). I’m trying to do that by the following:

MyExtender->AddToolBarExtension("Settings", EExtensionHook::After, NULL, FToolBarExtensionDelegate::CreateRaw(this, &HamadsPluginModule::AddToolbarExtension));

AddToolBarExtensions() returns the reference from the extension I did, so I can remove it later on. Now I’m trying to store that reference to a variable defined like this (In MyPlugin.h):

TSharedRef< FToolBarExtension > ToolbarExtension;

So I’m stuck here as it throws that error and I can’t continue.

Edit: AddToolBarExtension() returns a constant TSharedRef. So what I want to end up with is this:

ToolbarExtension = MyExtender->AddToolBarExtension( bla bla);

// ... And later

MyExtender->RemoveExtension(ToolbarExtension);

Hi,

TSharedRef is intended never to be null - this means it has no default constructor and must be initialised to a valid (non-null) state. If you would like an object that can be null, consider using a TSharedPtr, or initialise the TSharedRef with a valid pointer, for example:

FMyClass::FMyClass()
    : ToolbarExtension( MakeShareable( new FToolBarExtension ) )
{}

Hope that helps,

If you change ToolbarExtension to be a TSharedPtr the following code should work fine:

ToolbarExtension = MyExtender->AddToolBarExtension( bla bla);

// ... And later
if (ToolbarExtension.IsValid())
{
    MyExtender->RemoveExtension(ToolbarExtension.ToSharedRef());
}

For reference, TSharedRef will implicitly convert to TSharedPtr of the same template type, but the opposite is not true (since TSharedPtr can be null).

Alternatively, you could investigate using a TWeakPtr if you don’t want to keep the object alive in your module explicitly.

Defining ToolbarExtension like this:

TSharedPtr< FToolBarExtension > ToolbarExtension;

Throws this compile error:

**Error 1 error C2440: ‘initializing’ : cannot convert from 'const FToolBarExtension const ’ to 'FToolBarExtension ’ d:\000-myprojects\ue4\unrealengine\engine\source\runtime\core\public\templates\SharedPointer.h 525 1 UE4

So I redefined ToolbarExtension like this:

TSharedPtr< const FToolBarExtension > ToolbarExtension;

I had to add the const keyword since AddToolBarExtension() returns a const reference.

Now, I get a problem again at this line:

MyExtender->RemoveExtension(ToolbarExtension.ToSharedRef());

returns the following error:

**Error 1 error C2440: ‘initializing’ : cannot convert from 'const FToolBarExtension const ’ to 'const FExtensionBase ’ d:\000-myprojects\ue4\unrealengine\engine\source\runtime\core\public\templates\SharedPointer.h 207 1 UE4

I tried the weak ptr, it looks like this:

ToolbarExtender->RemoveExtension(ToolbarExtension.Pin().ToSharedRef());

And same error as above. I’m pretty much stuck.

Hello,

I tried this also:

void HamadsPluginModule::ShutdownModule()
{
	const TSharedRef< const FToolBarExtension > Extension = ToolbarExtension.ToSharedRef(); //this compiles ok

	ToolbarExtender->RemoveExtension(Extension); //err here
}

Error:

**Error 1 error C2440: ‘initializing’ : cannot convert from 'const FToolBarExtension const ’ to 'const FExtensionBase

No luck :frowning:

I haven’t tried compiling your specific example, but I can’t see from the code why you’d be presented with that compile error :frowning:

The only other thing I can suggest is explicitly casting it to the correct type á la:

ToolbarExtender->RemoveExtension(StaticCastSharedRef<const FExtensionBase>(ToolbarExtension.ToSharedRef()));

**Error 1 error C2440: ‘static_cast’ : cannot convert from 'const FToolBarExtension const ’ to 'const FExtensionBase

I searched the code base for an example usage of RemoveExtension(), but there is none. I hope Epic can change it in later builds to make it easier to use, because right now it’s a nightmare.

Hi, I’ve only just realised that FToolBarExtension is defined inside MultiBoxExtender.cpp. This would explain why the compiler cannot convert between the types - because it hasn’t seen the type, only a fwd declaration (I assume).

I expect this is a bug and would need resolving. In the mean time can you try moving the definition of that class into the header to see if that helps?

Nice catch, Andrew. I moved all the definitions (not just FToolBarExtension, but all its super class definitions which also exist in MultiBoxExtender.cpp) to the header, and worked immediately as intended.

I agree that this should be reported as a bug.

Just an update for you.

This bug has been fixed, and will be in 4.2, however, rather than put the types in the header, we’ve changed the AddXExtension functions to also return a TSharedRef to a FExtensionBase, that way there’s no type conversion required when passing it to Remove.

https://github.com/EpicGames/UnrealEngine/commit/381a29b6f4b3b5d1fea0a82595bec50d45e01853