0027104: DownCast() cannot return null for mismatched handle
[occt.git] / src / QANCollection / QANCollection_Handle.cxx
1 // Copyright (c) 2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <QANCollection.hxx>
15
16 #include <Draw.hxx>
17 #include <Draw_Interpretor.hxx>
18
19 #include <Message_Status.hxx>
20 #include <NCollection_StdAllocator.hxx>
21 #include <NCollection_IncAllocator.hxx>
22 #include <NCollection_HeapAllocator.hxx>
23 #include <OSD_Timer.hxx>
24 #include <Standard_Assert.hxx>
25 #include <Standard_DefineHandle.hxx>
26 #include <Standard_Transient.hxx>
27 #include <TCollection_AsciiString.hxx>
28 #include <Geom_Circle.hxx>
29 #include <Geom_Line.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <Geom_Surface.hxx>
32
33 #include <vector>
34 #include <memory>
35 #include <typeinfo>
36
37 // auxiliary macro to check and report status
38 #define CHECK(di,ok,what) di << "Checking " << what << (ok ? ": OK\n" : ": Error\n")
39
40 //=======================================================================
41 //function : QAHandleOps
42 //purpose  : Test Handle operations (mostly compile-time checks)
43 //=======================================================================
44
45 // set of overloaded functions for checking resolution of arguments
46 inline void f (const Handle(Geom_Curve)&) {}
47 inline void func (const Handle(Geom_Curve)&) {}
48 inline void func (const Handle(Geom_BSplineCurve)&) {}
49 inline void func (const Handle(Geom_Surface)&) {}
50 inline void func (const Handle(gp_Pnt)&) {}
51 inline void func (const Handle(gp_XYZ)&) {}
52 inline void func (const Handle(gp_Trsf)&) {}
53
54 static Standard_Integer QAHandleOps (Draw_Interpretor& theDI,
55                                      Standard_Integer  /*theArgNb*/,
56                                      const char**      /*theArgVec*/)
57 {
58   // ===============================================================
59   // Part 1: classes inheriting transient
60   // ===============================================================
61
62   Handle(Geom_Line) aLine = new Geom_Line (gp::Origin(), gp::DZ());
63   CHECK(theDI, ! aLine.IsNull(), "handle for non-null");
64
65   const Handle(Geom_Line)& cLine = aLine; // cast to self const ref
66   const Handle(Geom_Curve)& cCurve = aLine; // cast to base const ref
67   Geom_Line* pLine = aLine.get();
68   const Geom_Line* cpLine = aLine.get();
69   Geom_Line& rLine = *aLine;
70   const Geom_Line& crLine = *cLine;
71   Handle(Geom_Curve) aCurve = aLine; // copy from handle to derived type
72   aCurve = cLine; // assignment to handle of derived type
73   Handle(Geom_Line) dLine (cpLine); // copy from handle to derived type
74
75   aLine = Handle(Geom_Line)::DownCast (cCurve);
76   CHECK(theDI, ! aLine.IsNull(), "down cast");
77
78   // comparison operators
79   CHECK(theDI, aLine == aLine, "equality of handle to itself");
80   CHECK(theDI, cLine == cLine, "equality of const handle to itself");
81   CHECK(theDI, aLine == cLine, "equality of const and non-const handle");
82   CHECK(theDI, aLine == cCurve, "equality of handle and base handle");
83   CHECK(theDI, aLine == pLine,  "equality of handle and pointer");
84   CHECK(theDI, pLine == aLine,  "equality of pointer and handle");
85   CHECK(theDI, aLine == cpLine,  "equality of handle and const pointer");
86   CHECK(theDI, cpLine == aLine,  "equality of const pointer and handle");
87   CHECK(theDI, &rLine == aLine,  "equality of reference and handle");
88   CHECK(theDI, &crLine == aLine,  "equality of reference and handle");
89   CHECK(theDI, aLine, "cast to bool");
90
91   Handle(Geom_Line) aLin2;
92   CHECK(theDI, aLine != aLin2, "inequality of handle to the same type handle");
93   CHECK(theDI, aLin2 != cLine, "inequality of const and non-const handle");
94   CHECK(theDI, aLin2 != cCurve, "inequality of handle and base handle");
95   CHECK(theDI, aLin2 != pLine,  "inequality of handle and pointer");
96   CHECK(theDI, pLine != aLin2,  "inequality of pointer and handle");
97   CHECK(theDI, aLin2 != cpLine,  "inequality of handle and const pointer");
98   CHECK(theDI, cpLine != aLin2,  "inequality of const pointer and handle");
99
100   Handle(Geom_Curve) aCur2;
101   CHECK(theDI, aLine != aCur2, "inequality of handles of different types");
102   CHECK(theDI, aCur2 != cLine, "inequality of const and non-const handle");
103   CHECK(theDI, aCur2 != cCurve, "inequality of handle and base handle");
104   CHECK(theDI, aCur2 != pLine,  "inequality of handle and pointer");
105   CHECK(theDI, pLine != aCur2,  "inequality of pointer and handle");
106   CHECK(theDI, aCur2 != cpLine,  "inequality of handle and const pointer");
107   CHECK(theDI, cpLine != aCur2,  "inequality of const pointer and handle");
108
109   // passing handle as reference to base class
110   f (aLine);
111
112   // passing handle to overloaded function accepting handle to another type
113   // will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads
114 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
115   func (aLine);
116   func (cLine);
117 #endif
118
119   const Handle(Geom_Curve)& aCurve2 = aLine; // cast to base const ref
120
121   Handle(Geom_Line) qLine = cpLine; // constructor from const pointer -- could be made explicit...
122
123   // check whether compiler will destroy reference to temporary handle
124   const Handle(Geom_Curve)& aTmpRef (Handle(Geom_Line)::DownCast (aCurve2));
125   CHECK(theDI, ! aTmpRef.IsNull(),  "local reference of handle to base type to temporary handle object");
126
127   Handle(Geom_Surface) aSurf;
128   (void)aSurf;
129
130 #if 0
131   // each test in this section must cause compiler error
132   gunc (cLine); // passing const handle as non-const reference to base type
133   pLine = cLine.get(); // getting non-const pointer to contained object from const handle 
134   Handle(Geom_Line) xLine = cCurve; // copy from handle to base type
135   Handle(Geom_BSplineCurve) aBSpl (new Geom_Line (gp::Origin(), gp::DX())); // construction from pointer to incompatible type
136
137   CHECK(theDI, aLine == aSurf, "equality of handles of incompatible types");
138   CHECK(theDI, aSurf == cLine, "equality of const and non-const handle");
139   CHECK(theDI, aSurf == cCurve, "equality of handle and base handle");
140   CHECK(theDI, aSurf == pLine,  "equality of handle and pointer");
141   CHECK(theDI, pLine == aSurf,  "equality of pointer and handle");
142   CHECK(theDI, aSurf == cpLine,  "equality of handle and const pointer");
143   CHECK(theDI, cpLine != aSurf,  "equality of const pointer and handle");
144
145   CHECK(theDI, aLine != aSurf, "inequality of handles of incompatible types");
146   CHECK(theDI, aSurf != cLine, "inequality of const and non-const handle");
147   CHECK(theDI, aSurf != cCurve, "inequality of handle and base handle");
148   CHECK(theDI, aSurf != pLine,  "inequality of handle and pointer");
149   CHECK(theDI, pLine != aSurf,  "inequality of pointer and handle");
150   CHECK(theDI, aSurf != cpLine,  "inequality of handle and const pointer");
151   CHECK(theDI, cpLine != aSurf,  "inequality of const pointer and handle");
152 #endif
153
154   // ===============================================================
155   // Part 2: classes not inheriting transient
156   // ===============================================================
157 /*
158   Handle(gp_Pnt) aPnt = new gp_Pnt (gp::Origin());
159   CHECK(theDI, ! aPnt.IsNull(), "handle for non-null");
160
161   const Handle(gp_Pnt)& cPnt = aPnt; // cast to self const ref
162 //  const Handle(gp_XYZ)& cXYZ = aPnt; // cast to base const ref
163   gp_Pnt* pPnt = aPnt.get();
164   const gp_Pnt* cpPnt = aPnt.get();
165   gp_Pnt& rPnt = *aPnt;
166   const gp_Pnt& crPnt = *cPnt;
167 //  Handle(gp_XYZ) aXYZ = aPnt; // copy from handle to derived type
168 //  aXYZ = cPnt; // assignment to handle of derived type
169
170 //  aPnt = Handle(gp_Pnt)::DownCast (cXYZ);
171 //  CHECK(theDI, ! aPnt.IsNull(), "down cast");
172
173   // comparison operators
174   CHECK(theDI, aPnt == aPnt, "equality of handle to itself");
175   CHECK(theDI, cPnt == cPnt, "equality of const handle to itself");
176   CHECK(theDI, aPnt == cPnt, "equality of const and non-const handle");
177 //  CHECK(theDI, aPnt == cXYZ, "equality of handle and base handle");
178   CHECK(theDI, aPnt == pPnt,  "equality of handle and pointer");
179   CHECK(theDI, pPnt == aPnt,  "equality of pointer and handle");
180   CHECK(theDI, aPnt == cpPnt,  "equality of handle and const pointer");
181   CHECK(theDI, cpPnt == aPnt,  "equality of const pointer and handle");
182   CHECK(theDI, &rPnt == aPnt,  "equality of reference and handle");
183   CHECK(theDI, &crPnt == aPnt,  "equality of reference and handle");
184
185   Handle(gp_Pnt) aPnt2;
186   CHECK(theDI, aPnt != aPnt2, "inequality of handle to the same type handle");
187   CHECK(theDI, aPnt2 != cPnt, "inequality of const and non-const handle");
188 //  CHECK(theDI, aPnt2 != cXYZ, "inequality of handle and base handle");
189   CHECK(theDI, aPnt2 != pPnt,  "inequality of handle and pointer");
190   CHECK(theDI, pPnt != aPnt2,  "inequality of pointer and handle");
191   CHECK(theDI, aPnt2 != cpPnt,  "inequality of handle and const pointer");
192   CHECK(theDI, cpPnt != aPnt2,  "inequality of const pointer and handle");
193
194   Handle(gp_XYZ) aXYZ2;
195   CHECK(theDI, aLine != aPnt2, "inequality of handles of different types");
196   CHECK(theDI, aXYZ2 != cPnt, "inequality of const and non-const handle");
197 //  CHECK(theDI, aXYZ2 != cXYZ, "inequality of handle and base handle");
198 //  CHECK(theDI, aXYZ2 != pPnt,  "inequality of handle and pointer");
199 //  CHECK(theDI, pPnt != aXYZ2,  "inequality of pointer and handle");
200 //  CHECK(theDI, aXYZ2 != cpPnt,  "inequality of handle and const pointer");
201 //  CHECK(theDI, cpPnt != aXYZ2,  "inequality of const pointer and handle");
202
203   // passing handle as reference to base class
204   func (aPnt);
205   func (cPnt);
206 */
207   return 0;
208 }
209
210 //=======================================================================
211 //function : QAHandleBool
212 //purpose  : Test Handle -> bool conversion
213 //=======================================================================
214 static Standard_Integer QAHandleBool (Draw_Interpretor& theDI,
215                                       Standard_Integer  /*theArgNb*/,
216                                       const char**      /*theArgVec*/)
217 {
218   Handle(NCollection_BaseAllocator) aPtr = new NCollection_IncAllocator();
219
220   Handle(NCollection_IncAllocator) anInc = Handle(NCollection_IncAllocator)::DownCast (aPtr);
221   CHECK (theDI, ! anInc.IsNull(), "cast to NCollection_IncAllocator");
222
223   Handle(NCollection_BaseAllocator) anAlloc = aPtr;
224   CHECK (theDI, ! anAlloc.IsNull(), "cast to NCollection_BaseAllocator");
225   
226   Handle(NCollection_HeapAllocator) aHAlloc = Handle(NCollection_HeapAllocator)::DownCast (aPtr);
227   CHECK (theDI, aHAlloc.IsNull(), "cast to NCollection_HeapAllocator");
228
229   return 0;
230 }
231
232 // Auxiliary class to define new virtual methods
233 class Transient_Root : public Standard_Transient
234 {
235 public:
236   virtual const char* Name() const { return "Transient_Root"; }
237   virtual Standard_Transient* CreateParent() const { return new Standard_Transient; }
238   virtual Standard_Transient* Clone()        const { return new Transient_Root; }
239   DEFINE_STANDARD_RTTI_INLINE(Transient_Root,Standard_Transient)
240 };
241 DEFINE_STANDARD_HANDLE(Transient_Root, Standard_Transient)
242
243 // Auxiliary macros to create hierarchy of 50 classes
244 #define QA_DEFINECLASS(theClass, theParent) \
245 class theClass : public theParent \
246 { \
247 public:\
248   virtual const char* Name() const Standard_OVERRIDE { return #theClass; } \
249   virtual Standard_Transient* CreateParent() const Standard_OVERRIDE { return new theParent(); } \
250   virtual Standard_Transient* Clone()        const Standard_OVERRIDE { return new theClass(); } \
251   DEFINE_STANDARD_RTTI_INLINE(theClass,theParent) \
252 };\
253 DEFINE_STANDARD_HANDLE    (theClass, theParent) 
254
255 #define QA_NAME(theNum) qaclass ## theNum ## _ ## 50
256 #define QA_HANDLE_NAME(theNum) Handle(qaclass ## theNum ## _ ## 50)
257
258 #define QA_DEFINECLASS10(theParent, theTens) \
259 QA_DEFINECLASS(QA_NAME(theTens ## 0), theParent) \
260 QA_DEFINECLASS(QA_NAME(theTens ## 1), QA_NAME(theTens ## 0)) \
261 QA_DEFINECLASS(QA_NAME(theTens ## 2), QA_NAME(theTens ## 1)) \
262 QA_DEFINECLASS(QA_NAME(theTens ## 3), QA_NAME(theTens ## 2)) \
263 QA_DEFINECLASS(QA_NAME(theTens ## 4), QA_NAME(theTens ## 3)) \
264 QA_DEFINECLASS(QA_NAME(theTens ## 5), QA_NAME(theTens ## 4)) \
265 QA_DEFINECLASS(QA_NAME(theTens ## 6), QA_NAME(theTens ## 5)) \
266 QA_DEFINECLASS(QA_NAME(theTens ## 7), QA_NAME(theTens ## 6)) \
267 QA_DEFINECLASS(QA_NAME(theTens ## 8), QA_NAME(theTens ## 7)) \
268 QA_DEFINECLASS(QA_NAME(theTens ## 9), QA_NAME(theTens ## 8))
269
270 QA_DEFINECLASS10(Transient_Root,     0)
271 QA_DEFINECLASS10(qaclass09_50,       1)
272 QA_DEFINECLASS10(qaclass19_50,       2)
273 QA_DEFINECLASS10(qaclass29_50,       3)
274 QA_DEFINECLASS10(qaclass39_50,       4)
275 QA_DEFINECLASS  (qaclass50_50, qaclass49_50)
276
277 namespace
278 {
279   class qaclass50_50ANON : public qaclass49_50
280   {
281   public:
282     qaclass50_50ANON() {}
283   };
284 }
285
286 namespace QaNamespace
287 {
288   class qaclass50_50 : public qaclass49_50
289   {
290   public:
291     qaclass50_50() {}
292   };
293 }
294
295 namespace {
296 //! Timer sentry. Prints elapsed time information at destruction time.
297 class QATimer : public OSD_Timer
298 {
299 public:
300   enum TimeFormat
301   {
302     Seconds,
303     Milliseconds,
304     Microseconds,
305     Nanoseconds,
306     s  = Seconds,
307     ms = Milliseconds,
308     ns = Nanoseconds,
309   };
310
311 public:
312   //! Main constructor - automatically starts the timer.
313   QATimer (Draw_Interpretor& theDI,
314            Standard_CString       theTitle,
315            const TimeFormat       theFormat,
316            const Standard_Integer theNbIters = 1,
317            const Standard_Boolean theToPrintFormat = Standard_False)
318   : myDI(&theDI),
319     myTitle         (theTitle),
320     myFormat        (theFormat),
321     myNbIters       (theNbIters),
322     myToPrintFormat (theToPrintFormat)
323   {
324     Start();
325   }
326
327   //! Destructor - stops the timer and prints statistics.
328   ~QATimer()
329   {
330     Stop();
331     if (myTitle != NULL)
332     {
333       (*myDI) << myTitle;
334     }
335     switch (myFormat)
336     {
337       case Seconds:
338         (*myDI) <<  ElapsedTime() / Standard_Real(myNbIters);
339         if (myToPrintFormat)
340         {
341           (*myDI) << " s";
342         }
343         break;
344       case Milliseconds:
345         (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0;
346         if (myToPrintFormat)
347         {
348           (*myDI) << " ms";
349         }
350         break;
351       case Microseconds:
352         (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0;
353         if (myToPrintFormat)
354         {
355           (*myDI) << " microseconds";
356         }
357         break;
358       case Nanoseconds:
359         (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0;
360         if (myToPrintFormat)
361         {
362           (*myDI) << " ns";
363         }
364         break;
365     }
366   }
367
368 private:
369   Draw_Interpretor* myDI;
370   Standard_CString myTitle;         //!< timer description
371   TimeFormat       myFormat;        //!< time format
372   Standard_Integer myNbIters;       //!< iterations number
373   Standard_Boolean myToPrintFormat; //!< add time format
374 };
375 } // anonymous namespace
376
377 //=======================================================================
378 //function : QAHandleInc
379 //purpose  : Estimate the smart-pointer counter incrementing time
380 //=======================================================================
381 static Standard_Integer QAHandleInc (Draw_Interpretor& theDI,
382                                      Standard_Integer  theArgNb,
383                                      const char**      theArgVec)
384 {
385   if (theArgNb > 2)
386   {
387     std::cout << "Error: wrong syntax! See usage:\n";
388     theDI.PrintHelp (theArgVec[0]);
389     return 1;
390   }
391   const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi (theArgVec[1]) : 10000000;
392   if (aNbIters < 1)
393   {
394     std::cout << "Error: number of iterations should be positive!\n";
395     return 1;
396   }
397
398   Handle(Standard_Transient) aHandle  = new Standard_Transient();
399   std::shared_ptr<Standard_Transient> aSharePtr (new Standard_Transient());
400   theDI << "Time of creating and destroying " << aNbIters << " smart pointers to the same object, per item, ns:";
401   {
402     {
403       QATimer aTimer (theDI, "\nOCCT Handle: ", QATimer::ns, aNbIters);
404       {
405         std::vector<Handle(Standard_Transient)> aHandles (aNbIters);
406         for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
407         {
408           aHandles[anIter] = aHandle;
409         }
410       }
411     }
412     {
413       QATimer aTimer (theDI, "\nsC++ shared_ptr: ", QATimer::ns, aNbIters);
414       {
415         std::vector< std::shared_ptr<Standard_Transient> > aSharePointers (aNbIters);
416         for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
417         {
418           aSharePointers[anIter] = aSharePtr;
419         }
420       }
421     }
422   }
423   return 0;
424 }
425
426 //=======================================================================
427 //function : QAHandleKind
428 //purpose  :
429 //=======================================================================
430 static Standard_Integer QAHandleKind (Draw_Interpretor& /*theDI*/,
431                                       Standard_Integer  /*theArgNb*/,
432                                       const char**      /*theArgVec*/)
433 {
434   Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50);
435   Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50);
436   Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50);
437   Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50);
438   Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50);
439   Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50);
440
441   Handle(qaclass00_50) aHandle = new qaclass40_50();
442
443   #define QA_CHECK(theDesc, theExpr, theValue) \
444     {\
445       const bool isTrue = !!(theExpr); \
446       std::cout << theDesc << (isTrue ? " TRUE  " : " FALSE ") << (isTrue == theValue ? " is OK\n" : " is Error\n"); \
447     }
448
449   std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n";
450   for (Handle(Standard_Type) aType = aHandle->DynamicType(); ! aType.IsNull(); aType = aType->Parent())
451   {
452     std::cout << " - " << aType->Name() << "\n";
453   }
454
455   QA_CHECK ("Name == qaclass40_50       : ", TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(), true);
456
457   QA_CHECK ("IsKind     (aType00)       : ", aHandle->IsKind (aType00), true);
458   QA_CHECK ("IsKind     (aType10)       : ", aHandle->IsKind (aType10), true);
459   QA_CHECK ("IsKind     (aType20)       : ", aHandle->IsKind (aType20), true);
460   QA_CHECK ("IsKind     (aType30)       : ", aHandle->IsKind (aType30), true);
461   QA_CHECK ("IsKind     (aType40)       : ", aHandle->IsKind (aType40), true);
462   QA_CHECK ("IsKind     (aType50)       : ", aHandle->IsKind (aType50), false);
463
464   QA_CHECK ("IsKind     (\"qaclass00_50\"): ", aHandle->IsKind ("qaclass00_50"), true);
465   QA_CHECK ("IsKind     (\"qaclass10_50\"): ", aHandle->IsKind ("qaclass10_50"), true);
466   QA_CHECK ("IsKind     (\"qaclass20_50\"): ", aHandle->IsKind ("qaclass20_50"), true);
467   QA_CHECK ("IsKind     (\"qaclass30_50\"): ", aHandle->IsKind ("qaclass30_50"), true);
468   QA_CHECK ("IsKind     (\"qaclass40_50\"): ", aHandle->IsKind ("qaclass40_50"), true);
469   QA_CHECK ("IsKind     (\"qaclass50_50\"): ", aHandle->IsKind ("qaclass50_50"), false);
470
471   QA_CHECK ("IsInstance (aType00)       : ", aHandle->IsInstance (aType00), false);
472   QA_CHECK ("IsInstance (aType10)       : ", aHandle->IsInstance (aType10), false);
473   QA_CHECK ("IsInstance (aType20)       : ", aHandle->IsInstance (aType20), false);
474   QA_CHECK ("IsInstance (aType30)       : ", aHandle->IsInstance (aType30), false);
475   QA_CHECK ("IsInstance (aType40)       : ", aHandle->IsInstance (aType40), true);
476   QA_CHECK ("IsInstance (aType50)       : ", aHandle->IsInstance (aType50), false);
477
478 #ifdef HAVE_CPP11
479   std::cout << "\nC++11:\n";
480   std::type_index aCppType     = typeid(*aHandle.operator->());
481   std::cout << "typeid().name()    = '" << typeid(*aHandle.operator->()).name()     << "'\n";
482 #ifdef _MSC_VER
483   std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n";
484 #endif
485
486   std::cout << "[ANON]typeid().name()    = '" << typeid(qaclass50_50ANON).name()     << "'\n";
487 #ifdef _MSC_VER
488   std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n";
489 #endif
490
491   std::cout << "[NS]typeid().name()    = '" << typeid(QaNamespace::qaclass50_50).name()     << "'\n";
492 #ifdef _MSC_VER
493   std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name() << "'\n";
494 #endif
495
496   QA_CHECK ("is typeid  (aType00)       : ", typeid(*aHandle.operator->()) == typeid(qaclass00_50), false);
497   QA_CHECK ("is typeid  (aType10)       : ", typeid(*aHandle.operator->()) == typeid(qaclass10_50), false);
498   QA_CHECK ("is typeid  (aType20)       : ", typeid(*aHandle.operator->()) == typeid(qaclass20_50), false);
499   QA_CHECK ("is typeid  (aType30)       : ", typeid(*aHandle.operator->()) == typeid(qaclass30_50), false);
500   QA_CHECK ("is typeid  (aType40)       : ", typeid(*aHandle.operator->()) == typeid(qaclass40_50), true);
501   QA_CHECK ("is typeid  (aType50)       : ", typeid(*aHandle.operator->()) == typeid(qaclass50_50), false);
502
503   QA_CHECK ("is type_index (aType00)    : ", aCppType == typeid(qaclass00_50), false);
504   QA_CHECK ("is type_index (aType40)    : ", aCppType == typeid(qaclass40_50), true);
505
506   QA_CHECK ("IsClass(Standard_Transient): ", std::is_class<Standard_Transient>::value == !!STANDARD_TYPE(Standard_Transient)->IsClass(), true);
507   //QA_CHECK ("IsEnum (Message_Status)    : ", std::is_enum<Message_Status>::value == !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true);
508 #endif
509
510   return 0;
511 }
512
513 void QANCollection::CommandsHandle (Draw_Interpretor& theCommands)
514 {
515   const char* THE_GROUP = "QANCollection";
516   theCommands.Add ("QAHandleBool",
517                    "Test handle boolean operator",
518                    __FILE__, QAHandleBool, THE_GROUP);
519   theCommands.Add ("QAHandleInc",
520                    "QAHandleInc nbIter=1000000"
521                    "\n\t\t: Test handle increment performance",
522                    __FILE__, QAHandleInc,  THE_GROUP);
523   theCommands.Add ("QAHandleKind",
524                    "Test handle IsKind",
525                    __FILE__, QAHandleKind, THE_GROUP);
526   theCommands.Add ("QAHandleOps",
527                    "Test handle operations",
528                    __FILE__, QAHandleOps, THE_GROUP);
529   return;
530 }