“If you try to assign incompatible TSubclassOf types to each other you’ll get a compilation error.”
But in real life it doesn’t.
TSubclassOf<AActor> actorclass;
TSubclassOf<APawn> pawnclass;
actorclass = pawnclass; // Should be compiled ok.
pawnclass = actorclass ; // Should not be compiled BUT it does!
AActor* a1 = GetWorld()->SpawnActor( actorclass );
AActor* a2 = GetWorld()->SpawnActor<AActor>( actorclass );
AActor* a3= GetWorld()->SpawnActor( pawnclass );
// LogSpawn: Warning: SpawnActor failed because no class was specified
APawn* a4 = GetWorld()->SpawnActor<APawn>( pawnclass );
// LogSpawn: Warning: SpawnActor failed because no class was specified
You are correct that the statement in the TSubclassOf documentation is not entirely accurate. TSubclassOf is a template class that can hold a subclass of a specific class, and it is meant to be used as a type-safe way to reference subclasses of a certain class.
However, the template class itself is not type-safe in the sense that it does not enforce compatibility between different TSubclassOf types.
So, it is possible to assign a TSubclassOf<APawn> to a TSubclassOf<AActor> variable, but when you use it to spawn an actor using the SpawnActor method, you will get a warning message because the actual class that the TSubclassOf variable holds is not derived from AActor. And the same thing happened in the second example.
That means, you have to be extra careful when you use TSubclassOf in your code, as it does not enforce compatibility between different types of subclasses. This is something to be aware of when working with TSubclassOf, and it is always recommended to check the class before spawning it.
It’s worth mentioning that in recent versions of Unreal Engine, you can use the TSubclassOf<T>::Get() method to check the class that the variable holds. This can be helpful in situations where you want to ensure that the class is a derived class of the expected type.