0029911: Porting to Debian80-64 : Regressions in Foundation Classes
[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 // Note that if() is used to ensure that condition is
39 // evaluated before calls to stream output functions, to
40 // prevent side effects from such calls in cases when condition
41 // may contain references to freed objects in the stack.
42 #define CHECK(di,ok,what) \
43   if (ok) di << "Checking " << what << ": OK\n";\
44   else    di << "Checking " << what << ": Error\n"
45
46 //=======================================================================
47 //function : QAHandleOps
48 //purpose  : Test Handle operations (mostly compile-time checks)
49 //=======================================================================
50
51 // set of overloaded functions for checking resolution of arguments
52 inline void f (const Handle(Geom_Curve)&) {}
53 inline void func (const Handle(Geom_Curve)&) {}
54 inline void func (const Handle(Geom_BSplineCurve)&) {}
55 inline void func (const Handle(Geom_Surface)&) {}
56 inline void func (const Handle(gp_Pnt)&) {}
57 inline void func (const Handle(gp_XYZ)&) {}
58 inline void func (const Handle(gp_Trsf)&) {}
59
60 static Standard_Integer QAHandleOps (Draw_Interpretor& theDI,
61                                      Standard_Integer  /*theArgNb*/,
62                                      const char**      /*theArgVec*/)
63 {
64   // ===============================================================
65   // Part 1: classes inheriting transient
66   // ===============================================================
67
68   Handle(Geom_Line) aLine = new Geom_Line (gp::Origin(), gp::DZ());
69   CHECK(theDI, ! aLine.IsNull(), "handle for non-null");
70
71   const Handle(Geom_Line)& cLine = aLine; // cast to self const ref
72   const Handle(Geom_Curve)& cCurve = aLine; // cast to base const ref
73   Geom_Line* pLine = aLine.get();
74   const Geom_Line* cpLine = aLine.get();
75   Geom_Line& rLine = *aLine;
76   const Geom_Line& crLine = *cLine;
77   Handle(Geom_Curve) aCurve = aLine; // copy from handle to derived type
78   aCurve = cLine; // assignment to handle of derived type
79   Handle(Geom_Line) dLine (cpLine); // copy from handle to derived type
80
81   aLine = Handle(Geom_Line)::DownCast (cCurve);
82   CHECK(theDI, ! aLine.IsNull(), "down cast");
83
84   // comparison operators
85   CHECK(theDI, aLine == aLine, "equality of handle to itself");
86   CHECK(theDI, cLine == cLine, "equality of const handle to itself");
87   CHECK(theDI, aLine == cLine, "equality of const and non-const handle");
88   CHECK(theDI, aLine == cCurve, "equality of handle and base handle");
89   CHECK(theDI, aLine == pLine,  "equality of handle and pointer");
90   CHECK(theDI, pLine == aLine,  "equality of pointer and handle");
91   CHECK(theDI, aLine == cpLine,  "equality of handle and const pointer");
92   CHECK(theDI, cpLine == aLine,  "equality of const pointer and handle");
93   CHECK(theDI, &rLine == aLine,  "equality of reference and handle");
94   CHECK(theDI, &crLine == aLine,  "equality of reference and handle");
95   CHECK(theDI, aLine, "cast to bool");
96
97   Handle(Geom_Line) aLin2;
98   CHECK(theDI, aLine != aLin2, "inequality of handle to the same type handle");
99   CHECK(theDI, aLin2 != cLine, "inequality of const and non-const handle");
100   CHECK(theDI, aLin2 != cCurve, "inequality of handle and base handle");
101   CHECK(theDI, aLin2 != pLine,  "inequality of handle and pointer");
102   CHECK(theDI, pLine != aLin2,  "inequality of pointer and handle");
103   CHECK(theDI, aLin2 != cpLine,  "inequality of handle and const pointer");
104   CHECK(theDI, cpLine != aLin2,  "inequality of const pointer and handle");
105
106   Handle(Geom_Curve) aCur2;
107   CHECK(theDI, aLine != aCur2, "inequality of handles of different types");
108   CHECK(theDI, aCur2 != cLine, "inequality of const and non-const handle");
109   CHECK(theDI, aCur2 != cCurve, "inequality of handle and base handle");
110   CHECK(theDI, aCur2 != pLine,  "inequality of handle and pointer");
111   CHECK(theDI, pLine != aCur2,  "inequality of pointer and handle");
112   CHECK(theDI, aCur2 != cpLine,  "inequality of handle and const pointer");
113   CHECK(theDI, cpLine != aCur2,  "inequality of const pointer and handle");
114
115   // passing handle as reference to base class
116   f (aLine);
117
118   // passing handle to overloaded function accepting handle to another type
119   // will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads
120 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
121   func (aLine);
122   func (cLine);
123 #endif
124
125   const Handle(Geom_Curve)& aCurve2 = aLine; // cast to base const ref
126   CHECK (theDI, !aCurve2.IsNull (), "cast to base class const reference");
127
128   Handle(Geom_Line) qLine = cpLine; // constructor from const pointer -- could be made explicit...
129   
130   // check that compiler keeps temporary object referenced by local variable
131   const Handle(Geom_Line)& aTmpRef (Handle(Geom_Line)::DownCast (aCurve2));
132   // note that here and in similar checks below we use comparison of pointers instead 
133   // of checking handle for Null, since such check may fail if temporary object is
134   // destroyed prematurely and its location is used for other object. 
135   CHECK(theDI, aTmpRef.get() == aCurve2.get(),  "local reference of to temporary handle object");
136
137   // check undesired but logical situation: 
138   // compiler does not keep temporary object referenced by local variable of base type;
139   // here compiler does not recognize that it should keep the temporary object because handle
140   // classes do not inherit each other and they use hard cast for references to simulate inheritance
141   const Handle(Geom_Curve)& aTmpRefBase (Handle(Geom_Line)::DownCast (aCurve2));
142   CHECK(theDI, aTmpRefBase.get() != aCurve2.get(),  "local reference to temporary handle object (base type)");
143
144   // check operations with Handle_* classes
145   Handle(Geom_Line) hLine = aLine;
146   CHECK(theDI, ! hLine.IsNull(), "hhandle for non-null");
147
148   const Handle_Geom_Line& chLine = aLine; // cast to self const ref
149   const Handle_Geom_Curve& chCurve = aLine; // cast to base const ref
150   const Handle_Geom_Line& hhLine = hLine; // cast to self const ref
151   const Handle_Geom_Curve& hhCurve = hLine; // cast to base const ref
152   Handle_Geom_Curve hCurve = aLine; // copy from handle to derived type
153   Handle_Geom_Line phLine (aLine.get()); // construct from pointer
154
155   hLine = Handle_Geom_Line::DownCast (cCurve); // inheritance of downcast
156   CHECK(theDI, ! hLine.IsNull(), "down cast");
157
158   // comparison operators
159   CHECK(theDI, hLine == hLine, "equality of hhandle to itself");
160   CHECK(theDI, hLine == aLine, "equality of hhandle to handle");
161   CHECK(theDI, hhLine == hLine, "equality of hhandle to const");
162   CHECK(theDI, chLine == hLine, "equality of hhandle to const");
163   CHECK(theDI, hhCurve == hLine, "equality of hhandle to const");
164   CHECK(theDI, chCurve == hLine, "equality of hhandle to const");
165   CHECK(theDI, hLine, "cast to bool");
166
167   // passing hhandle as reference to base class
168   f (hLine);
169
170   // passing handle to overloaded function accepting handle to another type
171   // will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads
172 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
173   func (hLine);
174   func (chLine);
175 #endif
176
177   Handle_Geom_Line qhLine = cpLine; // constructor from const pointer -- could be made explicit...
178
179   // check that compiler keeps temporary object referenced by local variable
180   const Handle_Geom_Line& hTmpRef (Handle(Geom_Line)::DownCast (aCurve2));
181   CHECK(theDI, hTmpRef.get() == aCurve2.get(),  "local reference to temporary object (Handle_)");
182
183   // check lifetime of temporary object referenced by local variable (base type)
184   const Handle_Geom_Curve& hTmpRefBase (Handle(Geom_Line)::DownCast (aCurve2));
185   // here we have different behavior for MSVC 2013+ where Handle_ is a class
186   // (compiler creates temporary object of approprtiate type and keeps it living
187   // until the reference is valid) and other compilers where Handle_ is
188   // typedef to handle<> (compiler does not know that the reference that is being
189   // assigned is pointing to temporary object, due to involved type cast operation)
190 #if (defined(_MSC_VER) && _MSC_VER >= 1800) 
191   CHECK(theDI, hTmpRefBase.get() == aCurve2.get(),  "local reference to temporary handle object (Handle_ to base type)");
192 #else
193   CHECK(theDI, hTmpRefBase.get() != aCurve2.get(),  "local reference to temporary handle object (Handle_ to base type)");
194 #endif
195
196   Handle(Geom_Surface) aSurf;
197   (void)aSurf;
198
199 #if 0
200   // each test in this section must cause compiler error
201   gunc (cLine); // passing const handle as non-const reference to base type
202   pLine = cLine.get(); // getting non-const pointer to contained object from const handle 
203   Handle(Geom_Line) xLine = cCurve; // copy from handle to base type
204   Handle(Geom_BSplineCurve) aBSpl (new Geom_Line (gp::Origin(), gp::DX())); // construction from pointer to incompatible type
205
206   CHECK(theDI, aLine == aSurf,  "equality of handles of incompatible types");
207   CHECK(theDI, aSurf == cLine,  "equality of const and non-const handle");
208   CHECK(theDI, aSurf == cCurve, "equality of handle and base handle");
209   CHECK(theDI, aSurf == pLine,  "equality of handle and pointer");
210   CHECK(theDI, pLine == aSurf,  "equality of pointer and handle");
211   CHECK(theDI, aSurf == cpLine, "equality of handle and const pointer");
212   CHECK(theDI, cpLine != aSurf, "equality of const pointer and handle");
213
214   CHECK(theDI, aLine != aSurf,  "inequality of handles of incompatible types");
215   CHECK(theDI, aSurf != cLine,  "inequality of const and non-const handle");
216   CHECK(theDI, aSurf != cCurve, "inequality of handle and base handle");
217   CHECK(theDI, aSurf != pLine,  "inequality of handle and pointer");
218   CHECK(theDI, pLine != aSurf,  "inequality of pointer and handle");
219   CHECK(theDI, aSurf != cpLine, "inequality of handle and const pointer");
220   CHECK(theDI, cpLine != aSurf, "inequality of const pointer and handle");
221 #endif
222
223   // ===============================================================
224   // Part 2: classes not inheriting transient
225   // ===============================================================
226 /*
227   Handle(gp_Pnt) aPnt = new gp_Pnt (gp::Origin());
228   CHECK(theDI, ! aPnt.IsNull(), "handle for non-null");
229
230   const Handle(gp_Pnt)& cPnt = aPnt; // cast to self const ref
231 //  const Handle(gp_XYZ)& cXYZ = aPnt; // cast to base const ref
232   gp_Pnt* pPnt = aPnt.get();
233   const gp_Pnt* cpPnt = aPnt.get();
234   gp_Pnt& rPnt = *aPnt;
235   const gp_Pnt& crPnt = *cPnt;
236 //  Handle(gp_XYZ) aXYZ = aPnt; // copy from handle to derived type
237 //  aXYZ = cPnt; // assignment to handle of derived type
238
239 //  aPnt = Handle(gp_Pnt)::DownCast (cXYZ);
240 //  CHECK(theDI, ! aPnt.IsNull(), "down cast");
241
242   // comparison operators
243   CHECK(theDI, aPnt == aPnt, "equality of handle to itself");
244   CHECK(theDI, cPnt == cPnt, "equality of const handle to itself");
245   CHECK(theDI, aPnt == cPnt, "equality of const and non-const handle");
246 //  CHECK(theDI, aPnt == cXYZ, "equality of handle and base handle");
247   CHECK(theDI, aPnt == pPnt,  "equality of handle and pointer");
248   CHECK(theDI, pPnt == aPnt,  "equality of pointer and handle");
249   CHECK(theDI, aPnt == cpPnt,  "equality of handle and const pointer");
250   CHECK(theDI, cpPnt == aPnt,  "equality of const pointer and handle");
251   CHECK(theDI, &rPnt == aPnt,  "equality of reference and handle");
252   CHECK(theDI, &crPnt == aPnt,  "equality of reference and handle");
253
254   Handle(gp_Pnt) aPnt2;
255   CHECK(theDI, aPnt != aPnt2, "inequality of handle to the same type handle");
256   CHECK(theDI, aPnt2 != cPnt, "inequality of const and non-const handle");
257 //  CHECK(theDI, aPnt2 != cXYZ, "inequality of handle and base handle");
258   CHECK(theDI, aPnt2 != pPnt,  "inequality of handle and pointer");
259   CHECK(theDI, pPnt != aPnt2,  "inequality of pointer and handle");
260   CHECK(theDI, aPnt2 != cpPnt,  "inequality of handle and const pointer");
261   CHECK(theDI, cpPnt != aPnt2,  "inequality of const pointer and handle");
262
263   Handle(gp_XYZ) aXYZ2;
264   CHECK(theDI, aLine != aPnt2, "inequality of handles of different types");
265   CHECK(theDI, aXYZ2 != cPnt, "inequality of const and non-const handle");
266 //  CHECK(theDI, aXYZ2 != cXYZ, "inequality of handle and base handle");
267 //  CHECK(theDI, aXYZ2 != pPnt,  "inequality of handle and pointer");
268 //  CHECK(theDI, pPnt != aXYZ2,  "inequality of pointer and handle");
269 //  CHECK(theDI, aXYZ2 != cpPnt,  "inequality of handle and const pointer");
270 //  CHECK(theDI, cpPnt != aXYZ2,  "inequality of const pointer and handle");
271
272   // passing handle as reference to base class
273   func (aPnt);
274   func (cPnt);
275 */
276   return 0;
277 }
278
279 //=======================================================================
280 //function : QAHandleBool
281 //purpose  : Test Handle -> bool conversion
282 //=======================================================================
283 static Standard_Integer QAHandleBool (Draw_Interpretor& theDI,
284                                       Standard_Integer  /*theArgNb*/,
285                                       const char**      /*theArgVec*/)
286 {
287   Handle(NCollection_BaseAllocator) aPtr = new NCollection_IncAllocator();
288
289   Handle(NCollection_IncAllocator) anInc = Handle(NCollection_IncAllocator)::DownCast (aPtr);
290   CHECK (theDI, ! anInc.IsNull(), "cast to NCollection_IncAllocator");
291
292   Handle(NCollection_BaseAllocator) anAlloc = aPtr;
293   CHECK (theDI, ! anAlloc.IsNull(), "cast to NCollection_BaseAllocator");
294   
295   Handle(NCollection_HeapAllocator) aHAlloc = Handle(NCollection_HeapAllocator)::DownCast (aPtr);
296   CHECK (theDI, aHAlloc.IsNull(), "cast to NCollection_HeapAllocator");
297
298   return 0;
299 }
300
301 // Auxiliary class to define new virtual methods
302 class Transient_Root : public Standard_Transient
303 {
304 public:
305   virtual const char* Name() const { return "Transient_Root"; }
306   virtual Standard_Transient* CreateParent() const { return new Standard_Transient; }
307   virtual Standard_Transient* Clone()        const { return new Transient_Root; }
308   DEFINE_STANDARD_RTTI_INLINE(Transient_Root,Standard_Transient)
309 };
310 DEFINE_STANDARD_HANDLE(Transient_Root, Standard_Transient)
311
312 // Auxiliary macros to create hierarchy of 50 classes
313 #define QA_DEFINECLASS(theClass, theParent) \
314 class theClass : public theParent \
315 { \
316 public:\
317   virtual const char* Name() const Standard_OVERRIDE { return #theClass; } \
318   virtual Standard_Transient* CreateParent() const Standard_OVERRIDE { return new theParent(); } \
319   virtual Standard_Transient* Clone()        const Standard_OVERRIDE { return new theClass(); } \
320   DEFINE_STANDARD_RTTI_INLINE(theClass,theParent) \
321 };\
322 DEFINE_STANDARD_HANDLE    (theClass, theParent) 
323
324 #define QA_NAME(theNum) qaclass ## theNum ## _ ## 50
325 #define QA_HANDLE_NAME(theNum) Handle(qaclass ## theNum ## _ ## 50)
326
327 #define QA_DEFINECLASS10(theParent, theTens) \
328 QA_DEFINECLASS(QA_NAME(theTens ## 0), theParent) \
329 QA_DEFINECLASS(QA_NAME(theTens ## 1), QA_NAME(theTens ## 0)) \
330 QA_DEFINECLASS(QA_NAME(theTens ## 2), QA_NAME(theTens ## 1)) \
331 QA_DEFINECLASS(QA_NAME(theTens ## 3), QA_NAME(theTens ## 2)) \
332 QA_DEFINECLASS(QA_NAME(theTens ## 4), QA_NAME(theTens ## 3)) \
333 QA_DEFINECLASS(QA_NAME(theTens ## 5), QA_NAME(theTens ## 4)) \
334 QA_DEFINECLASS(QA_NAME(theTens ## 6), QA_NAME(theTens ## 5)) \
335 QA_DEFINECLASS(QA_NAME(theTens ## 7), QA_NAME(theTens ## 6)) \
336 QA_DEFINECLASS(QA_NAME(theTens ## 8), QA_NAME(theTens ## 7)) \
337 QA_DEFINECLASS(QA_NAME(theTens ## 9), QA_NAME(theTens ## 8))
338
339 QA_DEFINECLASS10(Transient_Root,     0)
340 QA_DEFINECLASS10(qaclass09_50,       1)
341 QA_DEFINECLASS10(qaclass19_50,       2)
342 QA_DEFINECLASS10(qaclass29_50,       3)
343 QA_DEFINECLASS10(qaclass39_50,       4)
344 QA_DEFINECLASS  (qaclass50_50, qaclass49_50)
345
346 namespace
347 {
348   class qaclass50_50ANON : public qaclass49_50
349   {
350   };
351 }
352
353 namespace QaNamespace
354 {
355   class qaclass50_50 : public qaclass49_50
356   {
357   public:
358     qaclass50_50() {}
359   };
360 }
361
362 namespace {
363 //! Timer sentry. Prints elapsed time information at destruction time.
364 class QATimer : public OSD_Timer
365 {
366 public:
367   enum TimeFormat
368   {
369     Seconds,
370     Milliseconds,
371     Microseconds,
372     Nanoseconds,
373     s  = Seconds,
374     ms = Milliseconds,
375     ns = Nanoseconds,
376   };
377
378 public:
379   //! Main constructor - automatically starts the timer.
380   QATimer (Draw_Interpretor& theDI,
381            Standard_CString       theTitle,
382            const TimeFormat       theFormat,
383            const Standard_Integer theNbIters = 1,
384            const Standard_Boolean theToPrintFormat = Standard_False)
385   : myDI(&theDI),
386     myTitle         (theTitle),
387     myFormat        (theFormat),
388     myNbIters       (theNbIters),
389     myToPrintFormat (theToPrintFormat)
390   {
391     Start();
392   }
393
394   //! Destructor - stops the timer and prints statistics.
395   ~QATimer()
396   {
397     Stop();
398     if (myTitle != NULL)
399     {
400       (*myDI) << myTitle;
401     }
402     switch (myFormat)
403     {
404       case Seconds:
405         (*myDI) <<  ElapsedTime() / Standard_Real(myNbIters);
406         if (myToPrintFormat)
407         {
408           (*myDI) << " s";
409         }
410         break;
411       case Milliseconds:
412         (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0;
413         if (myToPrintFormat)
414         {
415           (*myDI) << " ms";
416         }
417         break;
418       case Microseconds:
419         (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0;
420         if (myToPrintFormat)
421         {
422           (*myDI) << " microseconds";
423         }
424         break;
425       case Nanoseconds:
426         (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0;
427         if (myToPrintFormat)
428         {
429           (*myDI) << " ns";
430         }
431         break;
432     }
433   }
434
435 private:
436   Draw_Interpretor* myDI;
437   Standard_CString myTitle;         //!< timer description
438   TimeFormat       myFormat;        //!< time format
439   Standard_Integer myNbIters;       //!< iterations number
440   Standard_Boolean myToPrintFormat; //!< add time format
441 };
442 } // anonymous namespace
443
444 //=======================================================================
445 //function : QAHandleInc
446 //purpose  : Estimate the smart-pointer counter incrementing time
447 //=======================================================================
448 static Standard_Integer QAHandleInc (Draw_Interpretor& theDI,
449                                      Standard_Integer  theArgNb,
450                                      const char**      theArgVec)
451 {
452   if (theArgNb > 2)
453   {
454     std::cout << "Error: wrong syntax! See usage:\n";
455     theDI.PrintHelp (theArgVec[0]);
456     return 1;
457   }
458   const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi (theArgVec[1]) : 10000000;
459   if (aNbIters < 1)
460   {
461     std::cout << "Error: number of iterations should be positive!\n";
462     return 1;
463   }
464
465   Handle(Standard_Transient) aHandle  = new Standard_Transient();
466   opencascade::std::shared_ptr<Standard_Transient> aSharePtr (new Standard_Transient());
467   theDI << "Time of creating and destroying " << aNbIters << " smart pointers to the same object, per item, ns:";
468   {
469     {
470       QATimer aTimer (theDI, "\nOCCT Handle:    ", QATimer::ns, aNbIters);
471       {
472         std::vector<Handle(Standard_Transient)> aHandles (aNbIters);
473         for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
474         {
475           aHandles[anIter] = aHandle;
476         }
477       }
478     }
479     {
480       QATimer aTimer (theDI, "\nC++ shared_ptr: ", QATimer::ns, aNbIters);
481       {
482         std::vector< opencascade::std::shared_ptr<Standard_Transient> > aSharePointers (aNbIters);
483         for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
484         {
485           aSharePointers[anIter] = aSharePtr;
486         }
487       }
488     }
489   }
490   return 0;
491 }
492
493 //=======================================================================
494 //function : QAHandleKind
495 //purpose  :
496 //=======================================================================
497 static Standard_Integer QAHandleKind (Draw_Interpretor& /*theDI*/,
498                                       Standard_Integer  /*theArgNb*/,
499                                       const char**      /*theArgVec*/)
500 {
501   Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50);
502   Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50);
503   Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50);
504   Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50);
505   Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50);
506   Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50);
507
508   Handle(qaclass00_50) aHandle = new qaclass40_50();
509
510   #define QA_CHECK(theDesc, theExpr, theValue) \
511     {\
512       const bool isTrue = !!(theExpr); \
513       std::cout << theDesc << (isTrue ? " TRUE  " : " FALSE ") << (isTrue == theValue ? " is OK\n" : " is Error\n"); \
514     }
515
516   std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n";
517   for (Handle(Standard_Type) aType = aHandle->DynamicType(); ! aType.IsNull(); aType = aType->Parent())
518   {
519     std::cout << " - " << aType->Name() << "\n";
520   }
521
522   QA_CHECK ("Name == qaclass40_50       : ", TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(), true);
523
524   QA_CHECK ("IsKind     (aType00)       : ", aHandle->IsKind (aType00), true);
525   QA_CHECK ("IsKind     (aType10)       : ", aHandle->IsKind (aType10), true);
526   QA_CHECK ("IsKind     (aType20)       : ", aHandle->IsKind (aType20), true);
527   QA_CHECK ("IsKind     (aType30)       : ", aHandle->IsKind (aType30), true);
528   QA_CHECK ("IsKind     (aType40)       : ", aHandle->IsKind (aType40), true);
529   QA_CHECK ("IsKind     (aType50)       : ", aHandle->IsKind (aType50), false);
530
531   QA_CHECK ("IsKind     (\"qaclass00_50\"): ", aHandle->IsKind ("qaclass00_50"), true);
532   QA_CHECK ("IsKind     (\"qaclass10_50\"): ", aHandle->IsKind ("qaclass10_50"), true);
533   QA_CHECK ("IsKind     (\"qaclass20_50\"): ", aHandle->IsKind ("qaclass20_50"), true);
534   QA_CHECK ("IsKind     (\"qaclass30_50\"): ", aHandle->IsKind ("qaclass30_50"), true);
535   QA_CHECK ("IsKind     (\"qaclass40_50\"): ", aHandle->IsKind ("qaclass40_50"), true);
536   QA_CHECK ("IsKind     (\"qaclass50_50\"): ", aHandle->IsKind ("qaclass50_50"), false);
537
538   QA_CHECK ("IsInstance (aType00)       : ", aHandle->IsInstance (aType00), false);
539   QA_CHECK ("IsInstance (aType10)       : ", aHandle->IsInstance (aType10), false);
540   QA_CHECK ("IsInstance (aType20)       : ", aHandle->IsInstance (aType20), false);
541   QA_CHECK ("IsInstance (aType30)       : ", aHandle->IsInstance (aType30), false);
542   QA_CHECK ("IsInstance (aType40)       : ", aHandle->IsInstance (aType40), true);
543   QA_CHECK ("IsInstance (aType50)       : ", aHandle->IsInstance (aType50), false);
544
545 #ifdef HAVE_CPP11
546   std::cout << "\nC++11:\n";
547   std::type_index aCppType     = typeid(*aHandle.operator->());
548   std::cout << "typeid().name()    = '" << typeid(*aHandle.operator->()).name()     << "'\n";
549 #ifdef _MSC_VER
550   std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n";
551 #endif
552
553   std::cout << "[ANON]typeid().name()    = '" << typeid(qaclass50_50ANON).name()     << "'\n";
554 #ifdef _MSC_VER
555   std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n";
556 #endif
557
558   std::cout << "[NS]typeid().name()    = '" << typeid(QaNamespace::qaclass50_50).name()     << "'\n";
559 #ifdef _MSC_VER
560   std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name() << "'\n";
561 #endif
562
563   QA_CHECK ("is typeid  (aType00)       : ", typeid(*aHandle.operator->()) == typeid(qaclass00_50), false);
564   QA_CHECK ("is typeid  (aType10)       : ", typeid(*aHandle.operator->()) == typeid(qaclass10_50), false);
565   QA_CHECK ("is typeid  (aType20)       : ", typeid(*aHandle.operator->()) == typeid(qaclass20_50), false);
566   QA_CHECK ("is typeid  (aType30)       : ", typeid(*aHandle.operator->()) == typeid(qaclass30_50), false);
567   QA_CHECK ("is typeid  (aType40)       : ", typeid(*aHandle.operator->()) == typeid(qaclass40_50), true);
568   QA_CHECK ("is typeid  (aType50)       : ", typeid(*aHandle.operator->()) == typeid(qaclass50_50), false);
569
570   QA_CHECK ("is type_index (aType00)    : ", aCppType == typeid(qaclass00_50), false);
571   QA_CHECK ("is type_index (aType40)    : ", aCppType == typeid(qaclass40_50), true);
572
573   QA_CHECK ("IsClass(Standard_Transient): ", std::is_class<Standard_Transient>::value == !!STANDARD_TYPE(Standard_Transient)->IsClass(), true);
574   //QA_CHECK ("IsEnum (Message_Status)    : ", std::is_enum<Message_Status>::value == !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true);
575 #endif
576
577   return 0;
578 }
579
580 void QANCollection::CommandsHandle (Draw_Interpretor& theCommands)
581 {
582   const char* THE_GROUP = "QANCollection";
583   theCommands.Add ("QAHandleBool",
584                    "Test handle boolean operator",
585                    __FILE__, QAHandleBool, THE_GROUP);
586   theCommands.Add ("QAHandleInc",
587                    "QAHandleInc nbIter=1000000"
588                    "\n\t\t: Test handle increment performance",
589                    __FILE__, QAHandleInc,  THE_GROUP);
590   theCommands.Add ("QAHandleKind",
591                    "Test handle IsKind",
592                    __FILE__, QAHandleKind, THE_GROUP);
593   theCommands.Add ("QAHandleOps",
594                    "Test handle operations",
595                    __FILE__, QAHandleOps, THE_GROUP);
596   return;
597 }