This is what I am trying:
C
is a template parameter that is either SomeClass
or SomeDerivedClass
:
class SomeClass
{
protected:
int ProtectedBaseClassMember;
virtual void SomeFunctionFromBaseClass();
};
class SomeDerivedClass : public SomeClass { };
How to restrict C
to subclasses of SomeClass
?
template<class C>
class SmuggleInBetween : public C
{
public:
SmuggleInBetween()
{
// does not compile: unknown symbol "ProtectedBaseClassMember"
ProtectedBaseClassMember = 5;
// does compile, but ...
SomeClass* Me = static_cast<SomeClass>(this);
// ... member not accessible:
Me->ProtectedBaseClassMember = 5;
}
protected:
// doesn't compile: "method with override specifier did not override any base class method"
virtual void SomeFunctionFromBaseClass() override;
double DoubleProperty;
};
I found the very related question: Restrict C++ Template parameter to subclass, but over there the author seems fine just restricting the template parameter w/o ever accessing any symbols from the base class.
The use case for the templated SmuggleInBetween
class is this:
I can create
class SomeImprovedClass : public SmuggleInBetween<SomeClass> { };
and
class SomeImprovedDerivedClass : public SmuggleInBetween<SomeDerivedClass> { };
without having to duplicate the code that I smuggled in via this pattern (if possible).
Btw, this happens in the context of Unreal Engine. It might be that a solution that is possible in C++ still causes additional headache with the Unreal Header Tool that sometimes doesn't tolerate things that wander too far off the known paths.
This is one way to do it:
template<class C>
class SmuggleInBetween : public C
{
static_assert(std::is_base_of_v<SomeClass, C>, "C must be a descendant of SomeClass");
/* ... */
};
Of course, in general you could also use std::enable_if_v<std::is_base_of_v<SomeClass, C>, ...>
if you need SFINAE; here I think static_assert()
does the trick.