It might be best to skip to the code and read the comments for a quick introduction to what I'm trying to do, however there are more vital details I have to try to describe:
I want to add a member function to a class which is inherited through the class heirarchy. I want to make it so that derived classes don't have to retype any code or do anything special to automatically get this function, and I would like to avoid macros. This function should also be inherited by any subclasses made after compilation (this is part of a platform that other people will extend).
The function is a debugging function, which keeps track of the customised smart pointers (much like std::shared_ptr) that point to instances of the class - I want to be able to find out why a given instance is being held in memory, which means I need to know what pointers are pointing to it. The customised smart pointers are templated, and I want to enforce that the specialisation of the smart pointer used as the argument matches the type of the instance's static type.
Since this is in a framework, it is reasonably important to enable this function for people extending the hierarchy after compile.
This is being compiled on Windows with Visual Studio 2010. We're moving to VS 2015 soon, but I'd prefer not to wait. We're also mostly cross platform (we turn a couple of things off for other platforms, only when necessary). If there is a solution that would require C++11/14/17/later, I'd still like to hear it out of interest.
I feel like I need to make the function templated and specialised at the same time, specialised with some sort of 'Self', but I have no idea how to make subclasses get what is essentially copy-pasted, rather than inherited code. I also understand (I think) that this function is not appropriate to make virtual, but I also want to prevent subclasses from getting the parent classes' specialisation.
I think there are a few options I can go for, but I'd like to know if there's something better that I haven't thought of:
- Just give up on trying to achieve this kind of safety
- Use dynamic checking instead - I haven't worked out how to do this yet. I think it would be easier, but less safe, and I like safety.
- Use a macro to automatically make a typdef to Self, ala https://stackoverflow.com/a/21149648/78823
- I'm not sure exactly how this works. Either way, it's only half the problem, and I don't think it gets me any closer to solving the function declaration / inherit-but-not-really puzzle
- Also not a fan of forcing people to use a macro, especially for something that's only for debugging.
I'm fully expecting that a completely different design pattern would be the best solution, but such a solution hasn't occurred to me yet.
I really think the compiler would be able to know everything I need it to do support this, but I'm not sure the language does.
I would also very much appreciate some help or feedback about how to better word this question. I'm having a hard time getting my head around the problem myself, let alone wording it for other people to understand.
template<class T>
class CustomSmartPointer {};
class Base {
public:
void doSomething(CustomSmartPointer<Base> arg) {} //Should be able to say something like CustomSmartPointer<Self> instead, where the compiler knows what I mean by Self
};
class Derived : public Base {
public:
void doSomething(CustomSmartPointer<Derived> arg) {} //Shouldn't have to specify this declaration, or code, again, as it is direcly copy-pastable from above
};
class Derived2 : public Base {};
void main() {
Base b;
Derived d;
Derived2 d2;
CustomSmartPointer<Base> cb;
CustomSmartPointer<Derived> cd;
b.doSomething(cb);
d.doSomething(cd);
d2.doSomething(cb); //This shouldn't compile, as cb is the wrong type for the specialisation that should exist for Derived2::doSomething
}