I'm trying to cast from one generic to another, say:
myClass<MoreAbstract> anItem = myclass<DerivateFromMoreAbstract> anotherObject;
Or do something like
aFunction(anotherObject); // myclass<DerivateFromMoreAbstract> anotherObject
where aFunction signature is
aFunction(myClass<MoreAbstract> item);
In fact, myClass is actually a simplified implementation of shared_ptr I found online. I'm wondering if there's any way I can actually switch from one pointer type to another being encapsulated.
Is there any way to do such casting? If so, what would be the correct way to do it?
If it helps anyone, VC++ gives me this error:
Error 1 error C2440: 'type cast' : cannot convert from 'myClass<T>' to 'myClass<T>'
You can't static cast, as they are incompatible types. You can sometimes create an operator to coerce the type instead
#include <iostream>
class A { };
class B : public A { };
template<typename T>
struct holder {
T* value;
holder ( T*value ) : value ( value ) { }
template < typename U > // class T : public U
operator holder<U> () const
{
return holder<U>( value );
}
};
int main ()
{
using namespace std;
B b;
holder<B> hb ( &b );
holder<A> ha = hb;
cout << boolalpha;
cout << ( hb.value == ha.value ) << endl;
return 0;
}
Whether this is a meaningful operation rather depends on the semantic of the template class - if the aFunction
can put anything into the handler, you don't want the more specific object being mutated. Hence you copy somehow, either with a coercion operator or with a template copy constructor and assignment. ( the coercion is less code but might result in more objects being created if you don't use reference parameters )
Types aren't default convertible in this way (because you might not want objects to do that). In general, you could take two approaches:
Implement a explicit cast function, which might be useful for runtime casts, like boost's shared_ptr dynamic_pointer_cast. You'd end up with something like:
template <typename To, typename From>
myclass<To> myclass_cast(const myclass<From>&)
{ /* do a runtime cast, possibly with exceptions */ }
The second method is a converting constructor, which is good if it is decidable at compile time if they are convertable. For instance, if all classes are convertable from templated on Derived to templated on Base, here's a constructor that will only work when that is true (using enable_if and boost::type_traits):
template <typename To>
class myclass {
//converting constructor
template <typename From>
myclass(const myclass<From>&,
typename enable_if<boost::type_traits::is_base_of<To, From> >::type* dummy = 0)
{ }
};
Sorry, that is not possible. (Well, unless you do nasty reinterpret_cast
hacks, but you don't want to do that - the end result would not be pretty).
T<Base>
and T<Derived>
are not related. Compiler cannot assume that - remember that it is entirely possible that T was specialized for Derived to be something completely different.
Templates in c++ aswell as generics in c++.net are not covariant.
Check this question, might give you an idea for a workaround.
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