In C++, I'd like to be able to do the following:
struct IWrapper {
template<typename U>
U* dynamic_cast_to() { ??? } // what to do here?
};
template<typename T>
struct Wrapper : IWrapper {
Wrapper(T* _p) :p(_p) {}
T* p;
};
With this I'd like to be able to do
SomeDerived *a = new SomeDerived;
IWrapper *x = new Wrapper<SomeDerived>(a);
SomeBase *b = x->dynamic_cast_to<SomeBase>()
dynamic_cast_to() should return a pointer if indeed SomeDerived inherits from SomeBase and NULL if not, the same way normal dynamic_cast works.
Is this even possible?
give IWrapper a virtual destructor and use dynamic_cast.
i am amazed that the question is asked, how to implement a dynamic_cast_to function.
how can one avoid considering standard dynamic_cast then?
I don't think this can be done for arbitrary types T and U. The reason is that
the compiler has to generate the dynamic_cast code for the specific pair of types at compile time,
and there is no place where both types are known simultaneously at compile time.
If you could restrict IWrapper to just work for types derived from a certain base that had a virtual member function, then it could work like this:
struct IWrapper {
template<typename U>
U* dynamic_cast_to() { return dynamic_cast<U*>(commonBasePtr()); }
virtual CommonBase* commonBasePtr() = 0;
};
template<typename T>
struct Wrapper : IWrapper {
Wrapper(T* _p) :p(_p) {}
T* p;
virtual CommonBase* commonBasePtr() { return p; }
};
Not possible like that, because IWrapper doesn't know anything about T, nor has it access to the pointer. This should work:
template <typename T>
struct IWrapper {
IWrapper(T* p) : p_(p) {}
template<typename U>
U* dynamic_cast_to() { return dynamic_cast<U*>(p_); }
private:
T* p_;
};
template<typename T>
struct Wrapper : IWrapper<T> {
Wrapper(T* _p) : IWrapper<T>(_p), p(_p) {}
T* p;
};
struct SomeBase {
int a;
};
struct SomeDerived : public SomeBase {
int b;
};
int main()
{
SomeDerived *a = new SomeDerived;
IWrapper<SomeDerived> *x = new Wrapper<SomeDerived>(a);
SomeBase *b = x->dynamic_cast_to<SomeBase>();
return b->a;
}
Related
So an A* pointer can point to any object having a base A, and a B* pointer can point to any object with a base B*. Is there anyway to make a pointer that can only point to objects that have both A and B as a base?
I'd also want it to be something I can store as a class member (perhaps a smart version) without making that class a template class.
Edit:
#KerrekSB asked below what the point of this is. Basically I want to make a number of pure virtual base classes (i.e. interfaces) say printable, flyable, something_else_able etc.
And then I might have a new class which requires in it's constructor requires something which is both printable and flyable. If it was just one or the other, you could store it as a (smart) pointer and let polymorphism take care of the rest, but I'm trying to work out how to do this if the class uses both bases.
Sure, you can use a type trait:
#include <type_traits>
template <typename T, typename A, typename B> struct has_two_bases
: std::integral_constant<bool, std::is_base_of<A, T>:: value &&
std::is_base_of<B, T>:: value> { }
Usage:
static_assert(has_two_bases<T, A, B>::value, "Not a good type");
T * p;
Does something like this fit the bill?
class W {};
class X {};
class Y {};
class Z : public X, public Y {};
template <typename A, typename B>
class DualPointer {
public:
template <typename T>
DualPointer(T *t) : a_ptr_(t), b_ptr_(t) {}
operator A*() { return a_ptr_; }
operator B*() { return b_ptr_; }
private:
A *a_ptr_;
B *b_ptr_;
};
int main() {
Z z;
DualPointer<X, Y> p(&z);
X *x = p;
Y *y = p;
return 0;
}
Or if you're in a C++11 mood:
template <typename... Ts>
class MultiPointer;
template <typename T, typename... Rest>
class MultiPointer<T, Rest...> : public MultiPointer<Rest...> {
public:
template <typename U>
MultiPointer(U *u) : MultiPointer<Rest...>(u), ptr_(u) {};
operator T*() { return ptr_; }
private:
T *ptr_;
};
template <>
class MultiPointer<> {
public:
MultiPointer(void *) {}
};
int main() {
Z z;
MultiPointer<X, Y> p(&z);
X *x = p;
Y *y = p;
return 0;
}
If you're worried about the double storage of pointers, this approach doesn't work. See comments below this answer as to why incorporating Paweł's suggestion of using a union, which works if and only if all the pointers are numerically identical (that is, there's no multiple inheritance or other shenanigans using adjusted this pointers going on), is unsafe and basically useless.
// DON'T USE THIS VARIANT!!!!
template <typename... Ts>
class MultiPointer {
public:
MultiPointer(void *) {}
};
template <typename T, typename... Rest>
class MultiPointer<T, Rest...> {
public:
template <typename U> MultiPointer(U *u) : rest_(u) { ptr_ = u; };
template <typename U> operator U*() const { return rest_; }
operator T*() const { return ptr_; }
private:
union {
T *ptr_;
MultiPointer<Rest...> rest_;
};
};
While you could write a pointer wrapper class (similar to "smart pointers", but not so smart in this case) which only accepts pointers to types derived from A and B, dereferencing them becomes ambiguous. This is a conceptual problem you can't solve with any method.
But you could provide two functions toA() and toB() and/or conversion operators in order to retrieve a pointer to one of the base classes. But as said, you can't (nicely) overload operator* to retrieve the base reference depending on the context (depending on whether an A* or a B* is needed in the context). Same with operator->.
template<typename A, typename B>
class DualPointer {
A *a; // We need two separate pointers because their distance is not known
B *b;
public:
template<typename T>
DualPointer(T* object) :
a(object),
b(object)
{ }
A *toA() const { return a; }
B *toB() const { return b; }
operator A* () const { return a; }
operator B* () const { return b; }
};
Using SFINAE you can also allow a function template which has the actual type as the template parameter, like to<MyBaseA>():
template<typename T>
typename std::enable_if<std::is_same<A, T>::value, T*>::type
to() {
return a;
}
template<typename T>
typename std::enable_if<std::is_same<B, T>::value, T*>::type
to() {
return b;
}
Demonstration of this wrapper class
You can then add such a pointer as a class member as requested in your question:
class MyClass {
DualPointer<MyBaseA, MyBaseB> pointer;
};
and access the pointer like:
pointer.toA()->memberFunctionOfA();
If your types A and B are fixed, then either drop the "template" line and replace A and B accordingly, or add a typedef DualPointer<MyBaseA, MyBaseB> MyAOrB;
Expanding on this, you could say one of the two base classes, say the first, is your "main" base class. That could then be the one the pointer acts like, so the one returned by operator* and operator->. The two operators would then look like:
A * operator-> () const { return a; }
A & operator* () const { return *a; }
Then the call from above can become as easy as
pointer->memberFunctionOfA();
but not simultaneously
pointer->memberFunctionOfB();
Is there an alternative to using dynamic_cast in C++?
For example, in the code below, I want to be able to have Cat objects purr. But only Cat objects and not Dog objects. I know this goes against deriving the class from Mammal since it's not very polymorphic, but I still want to know if I can do this without dynamic_cast.
My class declarations
class Mammal
{
public:
virtual void Speak() const {cout << "Mammals yay!\n";}
};
class Cat: public Mammal
{
public:
void Speak() const{cout << "Meow\n";}
void Purr() const {cout <"rrrrrrrr\n";}
};
class Dog: public Mammal
{
public:
void Speak() const{cout << "Woof!\n";}
};
In Main
int main()
{
Mammal *pMammal;
pMammal = new Cat;
pMammal->Purr(); //How would I call this without having to use dynamic_cast?
return 0;
}
If you know there is a fixed set of implementations, you can create virtual functions that do the casting for you. This can ne cheaper than dynamic_cast.
So:
struct Cat;
struct Mammal {
virtual Cat* AsCat(){ return nullptr; }
};
struct Cat : Mammal {
virtual Cat* AsCat() { return this; }
};
I have done this with template tomfoolery in C++11 so you can even make it look like a cast.
#include <utility>
#include <iostream>
template<typename T>
struct fast_castable_leaf {
virtual T* do_fast_cast(T* unused=nullptr) { return nullptr; }
virtual T const* do_fast_cast(T* unused=nullptr) const { return nullptr; }
virtual ~fast_castable_leaf() {}
};
template<typename Tuple>
struct fast_castable;
template<template<typename...>class Tuple>
struct fast_castable<Tuple<>> {
virtual ~fast_castable() {}
};
template<template<typename...>class Tuple, typename T, typename... Ts>
struct fast_castable<Tuple<T,Ts...>>:
fast_castable_leaf<T>,
fast_castable<Tuple<Ts...>>
{};
template<typename T> struct block_deduction { typedef T type; };
template<typename T> using NoDeduction = typename block_deduction<T>::type;
template<typename T>
T* fast_cast( NoDeduction<fast_castable_leaf<T>>* src ) {
return src->do_fast_cast();
}
template<typename T>
T const* fast_cast( NoDeduction<fast_castable_leaf<T>> const* src ) {
return src->do_fast_cast();
}
template<typename T, typename D>
struct fast_cast_allowed : std::integral_constant<bool,
std::is_base_of<T,D>::value || std::is_same<T,D>::value
> {};
template<typename D, typename B, typename Tuple>
struct implement_fast_cast;
template<typename D, typename B, template<typename...>class Tuple>
struct implement_fast_cast<D,B,Tuple<>> : B {};
template<typename D, typename B, template<typename...>class Tuple, typename T, typename... Ts>
struct implement_fast_cast<D,B,Tuple<T,Ts...>> : implement_fast_cast<D, B, Tuple<Ts...>> {
private:
D* do_cast_work(std::true_type) { return static_cast<D*>(this); }
D const* do_cast_work(std::true_type) const { return static_cast<D const*>(this); }
std::nullptr_t do_cast_work(std::false_type) { return nullptr; }
std::nullptr_t do_cast_work(std::false_type) const { return nullptr; }
public:
T* do_fast_cast( T* unused = nullptr ) override { return do_cast_work( fast_cast_allowed<T,D>() ); }
T const* do_fast_cast( T* unused = nullptr ) const override { return do_cast_work( fast_cast_allowed<T,D>() ); }
};
And an example of the above framework in use:
struct Dog;
struct Cat;
struct Moose;
template<typename...>struct Types {};
typedef Types<Dog, Cat, Moose> Mammal_Types;
// A Mammal can be fast-casted to any of the Mammal_Types:
struct Mammal : fast_castable<Mammal_Types>
{};
// Cat wants to implement any legal fast_casts it can for Mammal in the
// set of Mammal_Types. You can save on overhead by doing Types<Cat> instead
// of Mammal_Types, but this is less error prone:
struct Cat : implement_fast_cast< Cat, Mammal, Mammal_Types >
{};
int main() {
Cat c;
Mammal* m=&c;
// so m is a pointer to a cat, but looks like a mammal. We use
// fast cast in order to turn it back into a Cat:
Cat* c2 = fast_cast<Cat>(m);
// and we test that it fails when we try to turn it into a Dog:
Dog* d2 = fast_cast<Dog>(m);
// This prints out a pointer value for c2, and 0 for d2:
std::cout << c2 << "," << d2 << "\n";
}
Live Example
This can be cleaned up to support a more standard fast_cast<Cat*> instead of a fast_cast<Cat>, as well as fast_cast<Cat&>, then blocking direct access to do_fast_cast by making it private and fast_cast a friend, and allowing for some means to have virtual inheritance in the case that you need it.
But the core of the system is above. You get cast-to-derived at the cost of a single virtual function lookup without having to maintain much of the machinery yourself.
Alternative implementation:
template<class...>struct types{using type=types;};
template<typename T>
struct fast_castable_leaf {
virtual T* do_fast_cast(T* unused=nullptr) { return nullptr; }
virtual T const* do_fast_cast(T* unused=nullptr) const { return nullptr; }
virtual ~fast_castable_leaf() {}
};
template<class Tuple>
struct fast_castable;
template<>
struct fast_castable<types<>> {
virtual ~fast_castable() {}
};
template<class T0, class...Ts>
struct fast_castable<types<T0, Ts...>>:
fast_castable_leaf<T0>,
fast_castable<types<Ts...>>
{};
template<class T> struct block_deduction { typedef T type; };
template<class T> using NoDeduction = typename block_deduction<T>::type;
template<class T>
T* fast_cast( NoDeduction<fast_castable_leaf<T>>* src ) {
return src->do_fast_cast();
}
template<class T>
T const* fast_cast( NoDeduction<fast_castable_leaf<T>> const* src ) {
return src->do_fast_cast();
}
template<class T, class D>
struct fast_cast_allowed : std::integral_constant<bool,
std::is_base_of<T,D>::value || std::is_same<T,D>::value
> {};
template<class Self, class Base, class Types>
struct implement_fast_cast;
template<class Self, class Base>
struct implement_fast_cast<Self,Base,types<>> : Base {
private:
template<class, class, class>
friend struct implement_fast_cast;
Self* do_cast_work(std::true_type) { return static_cast<Self*>(this); }
Self const* do_cast_work(std::true_type) const { return static_cast<Self const*>(this); }
std::nullptr_t do_cast_work(std::false_type) { return nullptr; }
std::nullptr_t do_cast_work(std::false_type) const { return nullptr; }
};
template<class Self, class Base, class T0, class... Ts>
struct implement_fast_cast<Self,Base,types<T0,Ts...>> :
implement_fast_cast<Self, Base, types<Ts...>>
{
public:
T0* do_fast_cast( T0* unused = nullptr ) override { return this->do_cast_work( fast_cast_allowed<T0,Self>() ); }
T0 const* do_fast_cast( T0* unused = nullptr ) const override { return this->do_cast_work( fast_cast_allowed<T0,Self>() ); }
};
struct Dog;
struct Cat;
struct Moose;
typedef types<Dog, Cat, Moose> Mammal_Types;
struct Mammal : fast_castable<Mammal_Types>
{};
struct Cat : implement_fast_cast< Cat, Mammal, Mammal_Types >
{};
int main() {
Cat c;
Mammal* m=&c;
Cat* c2 = fast_cast<Cat>(m);
Dog* d2 = fast_cast<Dog>(m);
std::cout << c2 << "," << d2 << "\n";
}
which might be easier for some compilers to swallow. Live example.
Note that for a long list of types, the above gets unwieldy (at both compile, and possibly run time), because it relies on linear inheritance.
A binary inheritance system would be a bit more complex to program, but would get rid of that problem. In it, you'd split your list of things to inherit from into two lists of equal size and inherit from both. The implement fast cast would have to inherit from Base via a virtual intermediary.
C++ doesn't support sending messages as, e.g., Objective C or Smalltalk do. To call a method you need to have a statically typed handle for an object supporting the method. Whether you need to use a dynamic_cast<Cat*>(pointer) or if you can get away with something else, e.g., a static_cast<Cat*>(pointer) is a separate question.
Since dynamic_cast<...>() is relatively expensive and trying a potentially unbounded number of different classes isn't feasible, it may be preferable to use a visit() method in the base class which is called with a visitor. However, these are just techniques to get hold of a properly typed reference.
You're dealing with a pointer to type Mammal and presumably Mammal does not define Purr(). You absolutely must cast it to a pointer to type Cat in order to access Purr(). You can do this with a C-style cast or a dynamic_cast, and the latter is generally the more proper thing to do in C++. dynamic_cast also has the advantage that you can use it to test, at runtime, whether your Mammal object is a Cat or not, so you can decide whether you can call Purr().
Three variants:
dynamic_cast, which you supposedly already aware of.
static_cast, which is compile-time cast, i.e. a) types are checked for compatibility b) offset between base class and derived class is calculated and taken into account c) there's no runtime check.
reinterpret_cast, which is also compile-time cast, done without any type check and without offset calculation. Use with caution - this cast might cause bugs very difficult to debug.
For complete reference and examples of these casts, look for some books and tutorials, for example: http://www.cplusplus.com/doc/tutorial/typecasting/
Consider the intention behind the following illegal C++11 code:
struct Base
{
template<typename U>
virtual U convert() = 0;
};
template<typename T>
struct Derived : Base
{
T t;
template<typename U>
virtual U convert() { return U(t); }
};
struct Any
{
Base* b;
template<typename U>
operator U() { return b->convert<U>(); }
};
int main()
{
Any a = ...;
string s = a; // s = a->b->t if T is convertible to string
// fails otherwise with compile error or runtime exception
// (either acceptable)
}
Is there a way to achieve the same or similiar effect with legal code?
(fyi the above way is illegal because templates may not be ‘virtual’)
Update:
struct Base
{
void* p;
type_info type;
};
template<typename T>
struct Derived : Base
{
Derived()
{
p = &t; // immovable
type = typeid(T);
}
T t;
};
struct Any
{
Base* b;
template<typename T = U, typename U>
operator U()
{
if (b->type != typeid(T))
throw exception();
T* t = (T*) b->p;
return U(*t);
}
};
Is this what you want?
struct Base
{
virtual void* convert(const std::type_info&) = 0;
};
template<typename T>
struct Derived : Base
{
virtual void* convert(const std::type_info& ti)
{ return typeid(T) == ti ? &t : nullptr; }
T t;
};
struct Any
{
Base* b;
template<typename U>
operator U()
{
if (auto p = b->convert(typeid(U)))
return *static_cast<U*>(p);
throw std::exception();
}
};
As the other answer says, it's hard to know exactly what you want as you've only shown invalid code, not explained what you're trying to achieve.
Edit oh I see now you want it to work for any convertible type, not just exact matches ... then no, you can't turn a type_info back into the type it represents, which would be needed for the derived type to test if the given type_info corresponded to a type that its stored type is convertible to. You need to know the correct type and specify it somehow, either explicitly or implicitly via deduction. If you then want to convert it to another type, you can do that separately:
Any a{ new Derived<int>() };
try {
char c = a; // throws
}
catch (...)
{
}
int i = a; // OK
char c = (int)a; // OK
Based on your update I think that this is what you are trying to do.
#include <typeinfo>
#include <exception>
#include <string>
template <typename T>
struct Any{
T* t;
Any():t(NULL){}
Any(const T& _t){
t=new T(_t);
}
template<typename U>
operator U(){
if(typeid(T)!=typeid(U) || t==NULL)
throw std::exception();
return *t;
}
};
int main (){
Any<std::string> a(std::string("Nothing"));
std::string b=a;
return 0;
};
If this doesn't help please explain in text not code what you are trying to achieve. It'll be useful to tell us also why you want to use those two extra classes Base and Derived.
Given a templated factory method, I would like to call different constructors based on the constructors the template parameter provides:
template<typename T>
T* Factory::create()
{
if (hasOnlyDefaultConstructor<T>())
return new T();
else
return new T(this);
}
Two problems:
If T does not have a constructor T(Factory*), then there are compilation problems.
How to write hasOnlyDefaultConstructor()?
In general I would like the following:
template<typename T>
T* Factory::create()
{
if (hasDefaultConstructor<T>())
return new T();
else if (hasUnaryConstructor<T>())
return new T(create());
else if (hasBinaryConstructor<T>())
return new T(create(), create());
else ....
}
Is there a way to achieve this in C++? I understand the problems if there are multiple constructors for the compiler to choose, but let's say that we only pass types T which have exactly one public constructor.
class A
{
A(B* b);
}
class B
{
B(C* c, D* d);
}
A* a = Factory::create<A>(); // same as A* a = new A(new B());
B* b = Factory::create<B>(); // same as B* b = new B(new C(), new D());
Shouldn't it be possible to write a generic function create(), which could instantiate both B and A?
Your example is a bit strange...
I would guess that you want something like:
template<typename T>
T* Factory::create()
{
return new T();
}
template<typename T, typename P0>
T* Factory::create(P0&& p0)
{
return new T(std::forward<P0>(p0));
}
template<typename T, typename P0, typename P1>
T* Factory::create(P0&& p0, P1&& p1)
{
return new T(std::forward<P0>(p0), std::forward<P1>(p1));
}
or with variadic templates:
template<typename T, typename... Args>
T* Factory::create(Args&&... args)
{
return new T(std::forward<Args>(args)...);
}
EDIT:
Based on comment below... still wierd from a memory management view.
template<typename T>
struct factory;
template<>
struct factory<A>
{
static A* create(){return new A(new B());}
}
template<>
struct factory<B>
{
static B* create(){return new B(new C(), new D());}
}
int main()
{
A* a = factory<A>::create();
B* b = factory<B>::create();
return 0;
}
You may want this:
struct X
{
enum {TYPE = 0;}// has default constructor
X() {}
};
struct A
{
enum {TYPE = 1;}
typedef B P;
A(P* p) {}
};
struct B
{
enum {TYPE = 2;}
typedef C P1;
typedef D P2;
B(P1* p1, P2* p2) {}
};
template<T, type> //type default = 0
struct FactoryDetail<T>
{
static T* create(){return new T(); }
};
template<T>
struct FactoryDetail<T, 1>
{
static T* create(){return new T(new typename T::P()); }
};
template<T>
struct FactoryDetail<T, 2>
{
static T* create(){return new T(new typename T::P1(), new typename T::P2()); }
};
//final Factory
template<T>
struct Factory
{
static T* create(){return FactoryDetail<T, T::TYPE>::create(); }
};
I don't have dev environment now, the above codes describing the basic idea.
I have a problem with template and wondering is there a possible way to achieve what I wanted to do. Here is my question.
template <typename T>
class A
{
public:
typedef T* pointer;
typedef const pointer const_pointer;
A()
{}
template <typename D>
A(const D& d)
{
// how can I store the D type
// so I can refer it later on
// outside of this function
}
};
ok here is a more complete code of what I wanted to do (it might not be compilable)
class C
{
public:
virtual ~C(){}
virtual void* get_d() = 0;
private:
};
template <typename T, typename D>
class Cimpl : public C
{
public:
Cimpl()
:t()
,d()
{}
Cimpl(const T& t, const D& d)
:t(t)
,(d)
{}
void* get_d()
{
return &reinterpret_cast<D&>(d);
}
private:
T t;
D d;
};
class B
{
public:
B()
:p(0)
{}
template <typename T, typename D>
B(const T& t, const D& d)
:p(0)
{
try
{
p = new Cimpl<T, D>(t, d);
}
catch(...)
{
d(p);
}
}
void* get_d()
{
return (p != 0) ? p->get_d() : 0;
}
~B()
{
delete p;
}
private:
C* p;
};
template <typename T>
class A
{
struct example_d
{
};
public:
typedef T* pointer;
typedef const pointer const_pointer;
A()
{}
template <typename D>
A(const T& t)
:b(t, example_d())
{
}
template <typename D>
A(const T& t, const D& d)
:b(t, d)
{
// how can I store the D type
// so I can refer it later on
// outside of this function
}
// not type safe...as user can cast to any type
// if I can store the type user pass in previous
// then I can use it back
template <typename T>
T* get_d()
{
reinterpret_cast<T*>(b.get_d());
}
private:
B b;
};
So I can use the class like
1)A<int> a(1);// with example_d as D
2)A<int> b(1, another_d()) // with another_d
I can change the template to take 2 parameters and use default parameter for 2nd type to be example_d. So I can achieve 1) but not 2). As I will have to code this way
A<int, another_d> b(1, another_d());
a bit too long to type...
You cannot store a type, you can only store objects.
(If you want to store the parameter d passed to A's constructor, look at type erasure.)
You can't "save" a typename like that. What you really want to do is make type D one of the template parameters of the class, e.g.
template <typename T, typename D>
class A
{
public:
typedef T* pointer;
typedef const pointer const_pointer;
A()
{}
A(const D& d)
{
}
};
Now, if your problem is that you want A<T> constructed with type D to be polymorphic with A<T> constructed with type E instead of having A<T,D> and A<T,E> be two different types, then the solution is a base class:
template <typename T>
class ABase
{
public:
typedef T* pointer;
typedef const pointer const_pointer;
ABase()
{}
protected:
/* You might want to omit this constructor completely,
* depending on your use case */
template<typename D>
ABase(const D& d)
{
}
};
template <typename T, typename D>
class A : public ABase<T>
{
public:
A()
{}
A(const D& d)
: ABase(d)
{
}
};
This looks like you are trying to create a template class that has a boost::any member variable. You should look at this a possible way of doing this.
Basically a boost::any can accept any value type. You can then retrieve that type safely if you know the type later. A good example of how you would use this is to store different datatypes in a map, (where you know the type later when you retrieve the the any by its name).
If this is not exactly what you are looking for the internals use a neat trick to implement it, and it will probably help you achieve what you are trying to do.
If you want to use type D in other member functions of class A, you can make D a second template parameter of class A.