I am facing a problem in my app where i want the qgraphicsitem_cast to cast items properly anywhere along hierarchy. I can't use dynamic_cast since i am compiling without rtti support.
Example:
if Base inherits QGraphicsItem and Derived inherits Base and both the classes define(or declare) Type as well type() which point to different values, then the cast fails even though its legal as shown below.
Qt Code:
  1. Derived *d = new Derived();
  2. QGraphicsItem *item = d;
  3. Q_ASSERT (qgraphicsitem_cast<Derived*>(item)); Succeeds
  4. Q_ASSERT (qgraphicsitem_cast<Base*>(item)); //This fails though legal :(
To copy to clipboard, switch view to plain text mode 

My current solution is custom cast function as shown
Qt Code:
  1. //stolen from source of qgraphicsitem_cast but modified to suit my needs
  2. template <class T> inline T graphicsitem_cast(QGraphicsItem *item)
  3. {
  4. bool firstCond = int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type);
  5. bool secondCond = !firstCond && item && ((int(static_cast<T>(0)->Type) & item->type()) == (int(static_cast<T>(0)->Type)));
  6. bool result = firstCond | secondCond;
  7. return result ? static_cast<T>(item) : 0;
  8. }
To copy to clipboard, switch view to plain text mode 
Notice the bitwise AND used in secondCond. qgraphicsitem_cast on other hand uses "==" and hence it fails.
Now I define my hierarcy as follows(with woking eg)
Qt Code:
  1. #include <QtGui>
  2.  
  3. //stolen from source of qgraphicsitem_cast but modified to suit my needs
  4. template <class T> inline T graphicsitem_cast(QGraphicsItem *item)
  5. {
  6. bool firstCond = int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type);
  7. bool secondCond = !firstCond && item && ((int(static_cast<T>(0)->Type) & item->type()) == (int(static_cast<T>(0)->Type)));
  8. bool result = firstCond | secondCond;
  9. return result ? static_cast<T>(item) : 0;
  10. }
  11.  
  12. const int startValue = 65536;
  13.  
  14. class Base : public QGraphicsLineItem
  15. {
  16. public:
  17. enum { Type = startValue };
  18. Base() : QGraphicsLineItem() {}
  19. int type() const { return Type;}
  20. };
  21.  
  22. class Derived1 : public Base
  23. {
  24. public:
  25. enum { Type = (startValue << 1) | Base::Type };
  26. Derived1() : Base() {}
  27. int type() const { return Type;}
  28. };
  29.  
  30. class Derived2 : public Derived1
  31. {
  32. public:
  33. enum { Type = (startValue << 2) | Derived1::Type };
  34. Derived2() : Derived1() {}
  35. int type() const { return Type;}
  36. };
  37.  
  38. int main()
  39. {
  40. Base *base = new Base();
  41. Derived1 *d1 = new Derived1();
  42. Derived2 *d2 = new Derived2();
  43.  
  44. QGraphicsItem *item = d2;
  45. if(graphicsitem_cast<Base*>(item) != 0) {
  46. //Check for crash
  47. item->setFlags( QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsSelectable );
  48. qDebug() << item->flags();
  49. }
  50. if(graphicsitem_cast<Derived1*>(item) != 0) {
  51. //Check for crash
  52. item->setFlags( QGraphicsItem::ItemIsFocusable );
  53. qDebug() << item->flags();
  54. }
  55. if(graphicsitem_cast<Derived2*>(item) != 0) {
  56. //Check for crash
  57. item->setFlags( QGraphicsItem::ItemIsSelectable );
  58. qDebug() << item->flags();
  59. }
  60. //All above succeeds
  61. return 0;
  62. }
To copy to clipboard, switch view to plain text mode 

The problem is I don't think this is elegant
Is there any elegant solution ? Can I use any template tricks in a better way ?