I have a base class IStructure which is derived by many classes.
Some of these classes 'reference' other IStructure classes. For example, my class class GuiButton : public IStructure has a member of Textstring (which derives from IStructure, as well).
Now I'm just glistening over this so I can get to the point, so this may seem weird to some of you. I would like to have a template class 'Reference' that references an IStructure. For example:
class GuiButton : public IStructure {
public:
Reference<Textstring> Text;
};
I know some of you might be wondering why I just don't do Textstring* Text. This is because some of these references are "external". The Reference template class only holds information about the IStructure (ie. Name, etc.). Some of these classes are insanely big and it would be pointless to instantiate that whole class to only use the Name property and what not. Does that make sense?
So now to my question:
class Textstring : public IStructure;
I can reference a Textstring by using my template:
Reference<Textstring> Text;
Now here's the issue: Some methods I have require me to upcast to `IStructure', for example:
void RegisterReference(Reference<IStructure> &reference);
So I couldn't do this:
Reference<Textstring> txt("TextName");
RegisterReference(txt); // error
I know I can cure this by not having Reference be a template, but I would really like to because it makes it easier to understand and know what type the reference is.
What are some ways I can accomplish this?
Thanks for your help!
-Alex
As @dasblinkenlight suggest, you could templatize your library functions. Or, you can add some "variance" to the Reference class:
template<typename T>
class Reference
{
// ...
public:
template<typename U>
Reference(Reference<U> const & r) {
// "copy" r into *this
}
};
Or with conversion operators
template<typename T>
class Reference
{
// ...
public:
template<typename U>
operator Reference<U>() {
// convert Reference<T> into Reference<U>
}
};
The downside of this approach is that you're actually creating new objects each time you need to upcast.
Thanks to Luc Danton for pointing this out. The code as I have written handles way more than upcasts. It'll do whatever conversions are available. To restrict things a little more nicely, we could do something like this (in C++11):
template<typename T>
class Reference
{
// ...
public:
template<typename U,
typename = typename std::enable_if<std::is_base_of<T, U>::value>::type>
Reference(Reference<U> const & r) {
// "copy" r into *this
}
};
You can make your function a template on the type parameter of the Reference, like this:
template <typename R>
void RegisterReference(Reference<R> &r);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With