0024870: Provide OCCT RTTI test cases
[occt.git] / src / QANCollection / QANCollection_Handle.cxx
CommitLineData
e8862cf4 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_Line.hxx>
29#include <Geom_BSplineCurve.hxx>
30#include <Geom_Surface.hxx>
31
32#include <vector>
33#include <memory>
34#include <typeinfo>
35
36#if defined(__GNUC__) && __cplusplus < 201103L
37#include <tr1/memory>
38#endif
39
40// auxiliary macro to check and report status
41#define CHECK(di,ok,what) di << "Checking " << what << (ok ? ": OK\n" : ": Error\n")
42
43//=======================================================================
44//function : QAHandleOps
45//purpose : Test Handle operations (mostly compile-time checks)
46//=======================================================================
47
48// set of overloaded functions for checking resolution of arguments
49inline void f (const Handle(Geom_Curve)&) {}
50inline void func (const Handle(Geom_Curve)&) {}
51inline void func (const Handle(Geom_BSplineCurve)&) {}
52inline void func (const Handle(Geom_Surface)&) {}
53inline void func (const Handle(gp_Pnt)&) {}
54inline void func (const Handle(gp_XYZ)&) {}
55inline void func (const Handle(gp_Trsf)&) {}
56
57inline void gunc (Handle(Geom_Curve)&) {}
58
59static Standard_Integer QAHandleOps (Draw_Interpretor& theDI,
60 Standard_Integer /*theArgNb*/,
61 const char** /*theArgVec*/)
62{
63 // ===============================================================
64 // Part 1: classes inheriting transient
65 // ===============================================================
66
67 Handle(Geom_Line) aLine = new Geom_Line (gp::Origin(), gp::DZ());
68 CHECK(theDI, ! aLine.IsNull(), "handle for non-null");
69
70 const Handle(Geom_Line)& cLine = aLine; // cast to self const ref
71 const Handle(Geom_Curve)& cCurve = aLine; // cast to base const ref
72 Geom_Line* pLine = aLine.get();
73 const Geom_Line* cpLine = aLine.get();
74 Geom_Line& rLine = *aLine;
75 const Geom_Line& crLine = *cLine;
76 Handle(Geom_Curve) aCurve = aLine; // copy from handle to derived type
77 aCurve = cLine; // assignment to handle of derived type
78 Handle(Geom_Line) dLine (cpLine); // copy from handle to derived type
79
80 aLine = Handle(Geom_Line)::DownCast (cCurve);
81 CHECK(theDI, ! aLine.IsNull(), "down cast");
82
83 // comparison operators
84 CHECK(theDI, aLine == aLine, "equality of handle to itself");
85 CHECK(theDI, cLine == cLine, "equality of const handle to itself");
86 CHECK(theDI, aLine == cLine, "equality of const and non-const handle");
87 CHECK(theDI, aLine == cCurve, "equality of handle and base handle");
88 CHECK(theDI, aLine == pLine, "equality of handle and pointer");
89 CHECK(theDI, pLine == aLine, "equality of pointer and handle");
90 CHECK(theDI, aLine == cpLine, "equality of handle and const pointer");
91 CHECK(theDI, cpLine == aLine, "equality of const pointer and handle");
92 CHECK(theDI, &rLine == aLine, "equality of reference and handle");
93 CHECK(theDI, &crLine == aLine, "equality of reference and handle");
94
95 Handle(Geom_Line) aLin2;
96 CHECK(theDI, aLine != aLin2, "inequality of handle to the same type handle");
97 CHECK(theDI, aLin2 != cLine, "inequality of const and non-const handle");
98 CHECK(theDI, aLin2 != cCurve, "inequality of handle and base handle");
99 CHECK(theDI, aLin2 != pLine, "inequality of handle and pointer");
100 CHECK(theDI, pLine != aLin2, "inequality of pointer and handle");
101 CHECK(theDI, aLin2 != cpLine, "inequality of handle and const pointer");
102 CHECK(theDI, cpLine != aLin2, "inequality of const pointer and handle");
103
104 Handle(Geom_Curve) aCur2;
105 CHECK(theDI, aLine != aCur2, "inequality of handles of different types");
106 CHECK(theDI, aCur2 != cLine, "inequality of const and non-const handle");
107 CHECK(theDI, aCur2 != cCurve, "inequality of handle and base handle");
108 CHECK(theDI, aCur2 != pLine, "inequality of handle and pointer");
109 CHECK(theDI, pLine != aCur2, "inequality of pointer and handle");
110 CHECK(theDI, aCur2 != cpLine, "inequality of handle and const pointer");
111 CHECK(theDI, cpLine != aCur2, "inequality of const pointer and handle");
112
113 // passing handle as reference to base class
114 f (aLine);
115
116 // passing handle to overloaded function accepting handle to another type
117 // will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads
118#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) || (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
119 func (aLine);
120 func (cLine);
121#endif
122
123 // passing handle as non-const reference to base type
124 // currently allowed for compatibility
125 gunc (aLine);
126 Handle(Geom_Curve)& aCurve2 = aLine; // cast to base non-const ref
127 (void)aCurve2;
128
129 Handle(Geom_Line) qLine = cpLine; // constructor from const pointer -- could be made explicit...
130
131 Handle(Geom_Surface) aSurf;
132 (void)aSurf;
133
134#if 0
135 // each test in this section must cause compiler error
136 gunc (cLine); // passing const handle as non-const reference to base type
137 pLine = cLine.get(); // getting non-const pointer to contained object from const handle
138 Handle(Geom_Line) xLine = cCurve; // copy from handle to base type
139 Handle(Geom_BSplineCurve) aBSpl (new Geom_Line (gp::Origin(), gp::DX())); // construction from pointer to incompatible type
140
141 CHECK(theDI, aLine == aSurf, "equality of handles of incompatible types");
142 CHECK(theDI, aSurf == cLine, "equality of const and non-const handle");
143 CHECK(theDI, aSurf == cCurve, "equality of handle and base handle");
144 CHECK(theDI, aSurf == pLine, "equality of handle and pointer");
145 CHECK(theDI, pLine == aSurf, "equality of pointer and handle");
146 CHECK(theDI, aSurf == cpLine, "equality of handle and const pointer");
147 CHECK(theDI, cpLine != aSurf, "equality of const pointer and handle");
148
149 CHECK(theDI, aLine != aSurf, "inequality of handles of incompatible types");
150 CHECK(theDI, aSurf != cLine, "inequality of const and non-const handle");
151 CHECK(theDI, aSurf != cCurve, "inequality of handle and base handle");
152 CHECK(theDI, aSurf != pLine, "inequality of handle and pointer");
153 CHECK(theDI, pLine != aSurf, "inequality of pointer and handle");
154 CHECK(theDI, aSurf != cpLine, "inequality of handle and const pointer");
155 CHECK(theDI, cpLine != aSurf, "inequality of const pointer and handle");
156#endif
157
158 // ===============================================================
159 // Part 2: classes not inheriting transient
160 // ===============================================================
161/*
162 Handle(gp_Pnt) aPnt = new gp_Pnt (gp::Origin());
163 CHECK(theDI, ! aPnt.IsNull(), "handle for non-null");
164
165 const Handle(gp_Pnt)& cPnt = aPnt; // cast to self const ref
166// const Handle(gp_XYZ)& cXYZ = aPnt; // cast to base const ref
167 gp_Pnt* pPnt = aPnt.get();
168 const gp_Pnt* cpPnt = aPnt.get();
169 gp_Pnt& rPnt = *aPnt;
170 const gp_Pnt& crPnt = *cPnt;
171// Handle(gp_XYZ) aXYZ = aPnt; // copy from handle to derived type
172// aXYZ = cPnt; // assignment to handle of derived type
173
174// aPnt = Handle(gp_Pnt)::DownCast (cXYZ);
175// CHECK(theDI, ! aPnt.IsNull(), "down cast");
176
177 // comparison operators
178 CHECK(theDI, aPnt == aPnt, "equality of handle to itself");
179 CHECK(theDI, cPnt == cPnt, "equality of const handle to itself");
180 CHECK(theDI, aPnt == cPnt, "equality of const and non-const handle");
181// CHECK(theDI, aPnt == cXYZ, "equality of handle and base handle");
182 CHECK(theDI, aPnt == pPnt, "equality of handle and pointer");
183 CHECK(theDI, pPnt == aPnt, "equality of pointer and handle");
184 CHECK(theDI, aPnt == cpPnt, "equality of handle and const pointer");
185 CHECK(theDI, cpPnt == aPnt, "equality of const pointer and handle");
186 CHECK(theDI, &rPnt == aPnt, "equality of reference and handle");
187 CHECK(theDI, &crPnt == aPnt, "equality of reference and handle");
188
189 Handle(gp_Pnt) aPnt2;
190 CHECK(theDI, aPnt != aPnt2, "inequality of handle to the same type handle");
191 CHECK(theDI, aPnt2 != cPnt, "inequality of const and non-const handle");
192// CHECK(theDI, aPnt2 != cXYZ, "inequality of handle and base handle");
193 CHECK(theDI, aPnt2 != pPnt, "inequality of handle and pointer");
194 CHECK(theDI, pPnt != aPnt2, "inequality of pointer and handle");
195 CHECK(theDI, aPnt2 != cpPnt, "inequality of handle and const pointer");
196 CHECK(theDI, cpPnt != aPnt2, "inequality of const pointer and handle");
197
198 Handle(gp_XYZ) aXYZ2;
199 CHECK(theDI, aLine != aPnt2, "inequality of handles of different types");
200 CHECK(theDI, aXYZ2 != cPnt, "inequality of const and non-const handle");
201// CHECK(theDI, aXYZ2 != cXYZ, "inequality of handle and base handle");
202// CHECK(theDI, aXYZ2 != pPnt, "inequality of handle and pointer");
203// CHECK(theDI, pPnt != aXYZ2, "inequality of pointer and handle");
204// CHECK(theDI, aXYZ2 != cpPnt, "inequality of handle and const pointer");
205// CHECK(theDI, cpPnt != aXYZ2, "inequality of const pointer and handle");
206
207 // passing handle as reference to base class
208 func (aPnt);
209 func (cPnt);
210*/
211 return 0;
212}
213
214//=======================================================================
215//function : QAHandleBool
216//purpose : Test Handle -> bool conversion
217//=======================================================================
218static Standard_Integer QAHandleBool (Draw_Interpretor& theDI,
219 Standard_Integer /*theArgNb*/,
220 const char** /*theArgVec*/)
221{
222 Handle(NCollection_BaseAllocator) aPtr = new NCollection_IncAllocator();
223
224 Handle(NCollection_IncAllocator) anInc = Handle(NCollection_IncAllocator)::DownCast (aPtr);
225 CHECK (theDI, ! anInc.IsNull(), "cast to NCollection_IncAllocator");
226
227 Handle(NCollection_BaseAllocator) anAlloc = Handle(NCollection_BaseAllocator)::DownCast (aPtr);
228 CHECK (theDI, ! anAlloc.IsNull(), "cast to NCollection_BaseAllocator");
229
230 Handle(NCollection_HeapAllocator) aHAlloc = Handle(NCollection_HeapAllocator)::DownCast (aPtr);
231 CHECK (theDI, aHAlloc.IsNull(), "cast to NCollection_HeapAllocator");
232
233 return 0;
234}
235
236// Auxiliary macros to create hierarchy of 50 classes
237#define QA_DEFINECLASS(theClass, theParent) \
238class theClass : public theParent \
239{ \
240public:\
241 theClass() {}; \
242 virtual ~theClass() {}; \
243 virtual const char* Name() const { return #theClass; } \
244 virtual Standard_Transient* CreateParent() const { return new theParent(); } \
245 virtual Standard_Transient* Clone() const { return new theClass(); } \
246 DEFINE_STANDARD_RTTI(theClass, theParent); \
247};\
248DEFINE_STANDARD_HANDLE (theClass, theParent) \
249IMPLEMENT_STANDARD_HANDLE (theClass, theParent) \
250IMPLEMENT_STANDARD_RTTIEXT(theClass, theParent)
251
252#define QA_NAME(theNum) qaclass ## theNum ## _ ## 50
253#define QA_HANDLE_NAME(theNum) Handle(qaclass ## theNum ## _ ## 50)
254
255#define QA_DEFINECLASS10(theParent, theTens) \
256QA_DEFINECLASS(QA_NAME(theTens ## 0), theParent) \
257QA_DEFINECLASS(QA_NAME(theTens ## 1), QA_NAME(theTens ## 0)) \
258QA_DEFINECLASS(QA_NAME(theTens ## 2), QA_NAME(theTens ## 1)) \
259QA_DEFINECLASS(QA_NAME(theTens ## 3), QA_NAME(theTens ## 2)) \
260QA_DEFINECLASS(QA_NAME(theTens ## 4), QA_NAME(theTens ## 3)) \
261QA_DEFINECLASS(QA_NAME(theTens ## 5), QA_NAME(theTens ## 4)) \
262QA_DEFINECLASS(QA_NAME(theTens ## 6), QA_NAME(theTens ## 5)) \
263QA_DEFINECLASS(QA_NAME(theTens ## 7), QA_NAME(theTens ## 6)) \
264QA_DEFINECLASS(QA_NAME(theTens ## 8), QA_NAME(theTens ## 7)) \
265QA_DEFINECLASS(QA_NAME(theTens ## 9), QA_NAME(theTens ## 8))
266
267QA_DEFINECLASS10(Standard_Transient, 0)
268QA_DEFINECLASS10(qaclass09_50, 1)
269QA_DEFINECLASS10(qaclass19_50, 2)
270QA_DEFINECLASS10(qaclass29_50, 3)
271QA_DEFINECLASS10(qaclass39_50, 4)
272QA_DEFINECLASS (qaclass50_50, qaclass49_50)
273
274namespace
275{
276 class qaclass50_50ANON : public qaclass49_50
277 {
278 public:
279 qaclass50_50ANON() {}
280 };
281}
282
283namespace QaNamespace
284{
285 class qaclass50_50 : public qaclass49_50
286 {
287 public:
288 qaclass50_50() {}
289 };
290}
291
292namespace {
293//! Timer sentry. Prints elapsed time information at destruction time.
294class QATimer : public OSD_Timer
295{
296public:
297 enum TimeFormat
298 {
299 Seconds,
300 Milliseconds,
301 Microseconds,
302 Nanoseconds,
303 s = Seconds,
304 ms = Milliseconds,
305 ns = Nanoseconds,
306 };
307
308public:
309 //! Main constructor - automatically starts the timer.
310 QATimer (Draw_Interpretor& theDI,
311 Standard_CString theTitle,
312 const TimeFormat theFormat,
313 const Standard_Integer theNbIters = 1,
314 const Standard_Boolean theToPrintFormat = Standard_False)
315 : myDI(&theDI),
316 myTitle (theTitle),
317 myFormat (theFormat),
318 myNbIters (theNbIters),
319 myToPrintFormat (theToPrintFormat)
320 {
321 Start();
322 }
323
324 //! Destructor - stops the timer and prints statistics.
325 ~QATimer()
326 {
327 Stop();
328 if (myTitle != NULL)
329 {
330 (*myDI) << myTitle;
331 }
332 switch (myFormat)
333 {
334 case Seconds:
335 (*myDI) << ElapsedTime() / Standard_Real(myNbIters);
336 if (myToPrintFormat)
337 {
338 (*myDI) << " s";
339 }
340 break;
341 case Milliseconds:
342 (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0;
343 if (myToPrintFormat)
344 {
345 (*myDI) << " ms";
346 }
347 break;
348 case Microseconds:
349 (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0;
350 if (myToPrintFormat)
351 {
352 (*myDI) << " microseconds";
353 }
354 break;
355 case Nanoseconds:
356 (*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0;
357 if (myToPrintFormat)
358 {
359 (*myDI) << " ns";
360 }
361 break;
362 }
363 }
364
365private:
366 Draw_Interpretor* myDI;
367 Standard_CString myTitle; //!< timer description
368 TimeFormat myFormat; //!< time format
369 Standard_Integer myNbIters; //!< iterations number
370 Standard_Boolean myToPrintFormat; //!< add time format
371};
372} // anonymous namespace
373
374//=======================================================================
375//function : QAHandleInc
376//purpose : Estimate the smart-pointer counter incrementing time
377//=======================================================================
378static Standard_Integer QAHandleInc (Draw_Interpretor& theDI,
379 Standard_Integer theArgNb,
380 const char** theArgVec)
381{
382 if (theArgNb > 2)
383 {
384 std::cout << "Error: wrong syntax! See usage:\n";
385 theDI.PrintHelp (theArgVec[0]);
386 return 1;
387 }
388 const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi (theArgVec[1]) : 10000000;
389 if (aNbIters < 1)
390 {
391 std::cout << "Error: number of iterations should be positive!\n";
392 return 1;
393 }
394
395 Handle(Standard_Transient) aHandle = new Standard_Transient();
396 std::tr1::shared_ptr<Standard_Transient> aSharePtr (new Standard_Transient());
397 theDI << "Time of creating and destroying " << aNbIters << " smart pointers to the same object, per item, ns:";
398 {
399 {
400 QATimer aTimer (theDI, "\nOCCT Handle: ", QATimer::ns, aNbIters);
401 {
402 std::vector<Handle(Standard_Transient)> aHandles (aNbIters);
403 for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
404 {
405 aHandles[anIter] = aHandle;
406 }
407 }
408 }
409 {
410 QATimer aTimer (theDI, "\nsC++ shared_ptr: ", QATimer::ns, aNbIters);
411 {
412 std::vector< std::tr1::shared_ptr<Standard_Transient> > aSharePointers (aNbIters);
413 for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
414 {
415 aSharePointers[anIter] = aSharePtr;
416 }
417 }
418 }
419 }
420 return 0;
421}
422
423namespace
424{
425 //! Auxiliary class to perform casting to specified type.
426 template<typename TTo> struct QACast
427 {
428 //! Perform casting using OCCT DownCast() operation.
429 template<typename TFrom>
430 static void doDownCast (Draw_Interpretor& theDI,
431 const Standard_Integer theNbIters,
432 const TFrom& theHandle)
433 {
434 std::vector<TTo> aHandles (theNbIters);
435 {
436 QATimer aTimer (theDI, " ", QATimer::ns, theNbIters);
437 for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter)
438 {
439 aHandles[anIter] = TTo::DownCast (theHandle);
440 }
441 }
442 }
443
444 //! Perform casting using standard C++ dynamic_cast<> operation.
445 template<typename TFrom>
446 static void doDynamicCast (Draw_Interpretor& theDI,
447 const Standard_Integer theNbIters,
448 const TFrom& theHandle)
449 {
450 std::vector<typename TTo::element_type*> aPointers (theNbIters);
451 {
452 QATimer aTimer (theDI, " ", QATimer::ns, theNbIters);
453 for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter)
454 {
455 aPointers[anIter] = dynamic_cast<typename TTo::element_type* > (theHandle.operator->());
456 }
457 }
458 }
459
460 //! Perform dynamic casting using shared_ptr::dynamic_pointer_cast operation.
461 template<typename TFrom>
462 static void doShareCast (Draw_Interpretor& theDI,
463 const Standard_Integer theNbIters,
464 const std::tr1::shared_ptr<TFrom>& theSharePtr)
465 {
466 std::vector< std::tr1::shared_ptr<typename TTo::element_type> > aSharePointers (theNbIters);
467 {
468 QATimer aTimer (theDI, " ", QATimer::ns, theNbIters);
469 for (Standard_Integer anIter = 0; anIter < theNbIters; ++anIter)
470 {
471 aSharePointers[anIter] = std::tr1::dynamic_pointer_cast<typename TTo::element_type, TFrom> (theSharePtr);
472 }
473 }
474 }
475
476 };
477
478 template<typename TAs>
479 static void qaCastAs (Draw_Interpretor& theDI,
480 const qaclass00_50& theInst,
481 const Standard_Integer theNbIters)
482 {
483 #define QA_TEST_CAST10(theTens, theDoCast) \
484 QACast<QA_HANDLE_NAME(theTens ## 0)>::theDoCast(theDI, theNbIters, aPtr); \
485 QACast<QA_HANDLE_NAME(theTens ## 1)>::theDoCast(theDI, theNbIters, aPtr); \
486 QACast<QA_HANDLE_NAME(theTens ## 2)>::theDoCast(theDI, theNbIters, aPtr); \
487 QACast<QA_HANDLE_NAME(theTens ## 3)>::theDoCast(theDI, theNbIters, aPtr); \
488 QACast<QA_HANDLE_NAME(theTens ## 4)>::theDoCast(theDI, theNbIters, aPtr); \
489 QACast<QA_HANDLE_NAME(theTens ## 5)>::theDoCast(theDI, theNbIters, aPtr); \
490 QACast<QA_HANDLE_NAME(theTens ## 6)>::theDoCast(theDI, theNbIters, aPtr); \
491 QACast<QA_HANDLE_NAME(theTens ## 7)>::theDoCast(theDI, theNbIters, aPtr); \
492 QACast<QA_HANDLE_NAME(theTens ## 8)>::theDoCast(theDI, theNbIters, aPtr); \
493 QACast<QA_HANDLE_NAME(theTens ## 9)>::theDoCast(theDI, theNbIters, aPtr);
494
495 typedef typename TAs::element_type aPtrType;
496 TAs aDummy (new aPtrType());
497 theDI << "Making a pointer:\n";
498 theDI << aDummy->DynamicType()->Name() << "* ptr = new " << theInst.DynamicType()->Name() << "\n";
499 theDI << "then measuring the time of casting it to base classes from qaclass00_50 to qaclass50_50, ns\n";
500 if (!theInst.IsKind (aDummy->DynamicType()))
501 {
502 return;
503 }
504
505 theDI << "\nOCCT Handle: ";
506 {
507 TAs aPtr ((typename TAs::element_type* )theInst.Clone());
508 QA_TEST_CAST10(0, doDownCast);
509 QA_TEST_CAST10(1, doDownCast);
510 QA_TEST_CAST10(2, doDownCast);
511 QA_TEST_CAST10(3, doDownCast);
512 QA_TEST_CAST10(4, doDownCast);
513 QACast<Handle(qaclass50_50)>::doDownCast(theDI, theNbIters, aPtr);
514 }
515 theDI << "\nC++ dynamic_cast: ";
516 {
517 TAs aPtr ((typename TAs::element_type* )theInst.Clone());
518 QA_TEST_CAST10(0, doDynamicCast);
519 QA_TEST_CAST10(1, doDynamicCast);
520 QA_TEST_CAST10(2, doDynamicCast);
521 QA_TEST_CAST10(3, doDynamicCast);
522 QA_TEST_CAST10(4, doDynamicCast);
523 QACast<Handle(qaclass50_50)>::doDynamicCast(theDI, theNbIters, aPtr);
524 }
525 theDI << "\nC++ dynamic_pointer_cast: ";
526 {
527 std::tr1::shared_ptr<typename TAs::element_type> aPtr ((typename TAs::element_type* )theInst.Clone());
528 QA_TEST_CAST10(0, doShareCast);
529 QA_TEST_CAST10(1, doShareCast);
530 QA_TEST_CAST10(2, doShareCast);
531 QA_TEST_CAST10(3, doShareCast);
532 QA_TEST_CAST10(4, doShareCast);
533 QACast<Handle(qaclass50_50)>::doShareCast(theDI, theNbIters, aPtr);
534 }
535 }
536
537}
538
539//=======================================================================
540//function : QAHandleCast
541//purpose : Estimate performance of RTTI mechanisms - dynamic type casting
542//=======================================================================
543static Standard_Integer QAHandleCast (Draw_Interpretor& theDI,
544 Standard_Integer theArgNb,
545 const char** theArgVec)
546{
547 if (theArgNb > 4)
548 {
549 std::cout << "Error: wrong syntax! See usage:\n";
550 theDI.PrintHelp (theArgVec[0]);
551 return 1;
552 }
553 Standard_Integer anArgIter = 0;
554 const Standard_Integer anInst = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 50;
555 const Standard_Integer aPtrTo = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 0;
556 const Standard_Integer aNbIters = (++anArgIter < theArgNb) ? Draw::Atoi (theArgVec[anArgIter]) : 1000000;
557
558 if (aNbIters < 1)
559 {
560 std::cout << "Error: number of iterations (" << aNbIters << ") should be positive!\n";
561 return 1;
562 }
563 if (anInst > 50 || anInst < 0)
564 {
565 std::cout << "Error: class instance (" << anInst << ") should be specified within 0..50 range!\n";
566 return 1;
567 }
568 if (aPtrTo > anInst || aPtrTo < 0)
569 {
570 std::cout << "Error: class pointer (" << aPtrTo << ") should be specified within 0.." << anInst << " range!\n";
571 return 1;
572 }
573 else if (aPtrTo % 10 != 0)
574 {
575 std::cout << "Error: class pointer (" << aPtrTo << ") should be multiple of 10!\n";
576 return 1;
577 }
578
579 Handle(qaclass00_50) aHandle = new qaclass50_50();
580 for (Standard_Integer anInstIter = 50 - anInst; anInstIter > 0; --anInstIter)
581 {
582 Handle(Standard_Transient) aParent (aHandle->CreateParent());
583 aHandle = Handle(qaclass00_50)::DownCast (aParent);
584 }
585
586 std::ios::fmtflags aFlags = std::cout.flags();
587 std::cout.precision (5);
588
589 #define QA_TEST_CASTAS10(theTens) \
590 case 10 * theTens + 0: qaCastAs<QA_HANDLE_NAME(theTens ## 0)>(theDI, *aHandle, aNbIters); break; \
591 case 10 * theTens + 1: qaCastAs<QA_HANDLE_NAME(theTens ## 1)>(theDI, *aHandle, aNbIters); break; \
592 case 10 * theTens + 2: qaCastAs<QA_HANDLE_NAME(theTens ## 2)>(theDI, *aHandle, aNbIters); break; \
593 case 10 * theTens + 3: qaCastAs<QA_HANDLE_NAME(theTens ## 3)>(theDI, *aHandle, aNbIters); break; \
594 case 10 * theTens + 4: qaCastAs<QA_HANDLE_NAME(theTens ## 4)>(theDI, *aHandle, aNbIters); break; \
595 case 10 * theTens + 5: qaCastAs<QA_HANDLE_NAME(theTens ## 5)>(theDI, *aHandle, aNbIters); break; \
596 case 10 * theTens + 6: qaCastAs<QA_HANDLE_NAME(theTens ## 6)>(theDI, *aHandle, aNbIters); break; \
597 case 10 * theTens + 7: qaCastAs<QA_HANDLE_NAME(theTens ## 7)>(theDI, *aHandle, aNbIters); break; \
598 case 10 * theTens + 8: qaCastAs<QA_HANDLE_NAME(theTens ## 8)>(theDI, *aHandle, aNbIters); break; \
599 case 10 * theTens + 9: qaCastAs<QA_HANDLE_NAME(theTens ## 9)>(theDI, *aHandle, aNbIters); break;
600
601 switch (aPtrTo)
602 {
603 // vc11 requires /bigobj option
604 //QA_TEST_CASTAS10(0)
605 //QA_TEST_CASTAS10(1)
606 //QA_TEST_CASTAS10(2)
607 //QA_TEST_CASTAS10(3)
608 //QA_TEST_CASTAS10(4)
609 case 0: qaCastAs<Handle(qaclass00_50)>(theDI, *aHandle, aNbIters); break;
610 case 10: qaCastAs<Handle(qaclass10_50)>(theDI, *aHandle, aNbIters); break;
611 case 20: qaCastAs<Handle(qaclass20_50)>(theDI, *aHandle, aNbIters); break;
612 case 30: qaCastAs<Handle(qaclass30_50)>(theDI, *aHandle, aNbIters); break;
613 case 40: qaCastAs<Handle(qaclass40_50)>(theDI, *aHandle, aNbIters); break;
614 case 50: qaCastAs<Handle(qaclass50_50)>(theDI, *aHandle, aNbIters); break;
615 }
616 std::cout.setf (aFlags);
617 return 0;
618}
619
620//=======================================================================
621//function : QAHandleKind
622//purpose :
623//=======================================================================
624static Standard_Integer QAHandleKind (Draw_Interpretor& /*theDI*/,
625 Standard_Integer /*theArgNb*/,
626 const char** /*theArgVec*/)
627{
628 Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50);
629 Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50);
630 Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50);
631 Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50);
632 Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50);
633 Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50);
634
635 Handle(qaclass00_50) aHandle = new qaclass40_50();
636
637 #define QA_CHECK(theDesc, theExpr, theValue) \
638 {\
639 const bool isTrue = !!(theExpr); \
640 std::cout << theDesc << (isTrue ? " TRUE " : " FALSE ") << (isTrue == theValue ? " is OK\n" : " is Error\n"); \
641 }
642
643 std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n";
644 for (Handle(Standard_Type) aType = aHandle->DynamicType(); ! aType.IsNull(); aType = aType->Parent())
645 {
646 std::cout << " - " << aType->Name() << "\n";
647 }
648
649 QA_CHECK ("Name == qaclass40_50 : ", TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(), true);
650
651 QA_CHECK ("IsKind (aType00) : ", aHandle->IsKind (aType00), true);
652 QA_CHECK ("IsKind (aType10) : ", aHandle->IsKind (aType10), true);
653 QA_CHECK ("IsKind (aType20) : ", aHandle->IsKind (aType20), true);
654 QA_CHECK ("IsKind (aType30) : ", aHandle->IsKind (aType30), true);
655 QA_CHECK ("IsKind (aType40) : ", aHandle->IsKind (aType40), true);
656 QA_CHECK ("IsKind (aType50) : ", aHandle->IsKind (aType50), false);
657
658 QA_CHECK ("IsKind (\"qaclass00_50\"): ", aHandle->IsKind ("qaclass00_50"), true);
659 QA_CHECK ("IsKind (\"qaclass10_50\"): ", aHandle->IsKind ("qaclass10_50"), true);
660 QA_CHECK ("IsKind (\"qaclass20_50\"): ", aHandle->IsKind ("qaclass20_50"), true);
661 QA_CHECK ("IsKind (\"qaclass30_50\"): ", aHandle->IsKind ("qaclass30_50"), true);
662 QA_CHECK ("IsKind (\"qaclass40_50\"): ", aHandle->IsKind ("qaclass40_50"), true);
663 QA_CHECK ("IsKind (\"qaclass50_50\"): ", aHandle->IsKind ("qaclass50_50"), false);
664
665 QA_CHECK ("IsInstance (aType00) : ", aHandle->IsInstance (aType00), false);
666 QA_CHECK ("IsInstance (aType10) : ", aHandle->IsInstance (aType10), false);
667 QA_CHECK ("IsInstance (aType20) : ", aHandle->IsInstance (aType20), false);
668 QA_CHECK ("IsInstance (aType30) : ", aHandle->IsInstance (aType30), false);
669 QA_CHECK ("IsInstance (aType40) : ", aHandle->IsInstance (aType40), true);
670 QA_CHECK ("IsInstance (aType50) : ", aHandle->IsInstance (aType50), false);
671
672#ifdef HAVE_CPP11
673 std::cout << "\nC++11:\n";
674 std::type_index aCppType = typeid(*aHandle.operator->());
675 std::cout << "typeid().name() = '" << typeid(*aHandle.operator->()).name() << "'\n";
676#ifdef _MSC_VER
677 std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n";
678#endif
679
680 std::cout << "[ANON]typeid().name() = '" << typeid(qaclass50_50ANON).name() << "'\n";
681#ifdef _MSC_VER
682 std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n";
683#endif
684
685 std::cout << "[NS]typeid().name() = '" << typeid(QaNamespace::qaclass50_50).name() << "'\n";
686#ifdef _MSC_VER
687 std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name() << "'\n";
688#endif
689
690 QA_CHECK ("is typeid (aType00) : ", typeid(*aHandle.operator->()) == typeid(qaclass00_50), false);
691 QA_CHECK ("is typeid (aType10) : ", typeid(*aHandle.operator->()) == typeid(qaclass10_50), false);
692 QA_CHECK ("is typeid (aType20) : ", typeid(*aHandle.operator->()) == typeid(qaclass20_50), false);
693 QA_CHECK ("is typeid (aType30) : ", typeid(*aHandle.operator->()) == typeid(qaclass30_50), false);
694 QA_CHECK ("is typeid (aType40) : ", typeid(*aHandle.operator->()) == typeid(qaclass40_50), true);
695 QA_CHECK ("is typeid (aType50) : ", typeid(*aHandle.operator->()) == typeid(qaclass50_50), false);
696
697 QA_CHECK ("is type_index (aType00) : ", aCppType == typeid(qaclass00_50), false);
698 QA_CHECK ("is type_index (aType40) : ", aCppType == typeid(qaclass40_50), true);
699
700 QA_CHECK ("IsClass(Standard_Transient): ", std::is_class<Standard_Transient>::value == !!STANDARD_TYPE(Standard_Transient)->IsClass(), true);
701 //QA_CHECK ("IsEnum (Message_Status) : ", std::is_enum<Message_Status>::value == !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true);
702#endif
703
704 return 0;
705}
706
707void QANCollection::CommandsHandle (Draw_Interpretor& theCommands)
708{
709 const char* THE_GROUP = "QANCollection";
710 theCommands.Add ("QAHandleBool",
711 "Test handle boolean operator",
712 __FILE__, QAHandleBool, THE_GROUP);
713 theCommands.Add ("QAHandleInc",
714 "QAHandleInc nbIter=1000000"
715 "\n\t\t: Test handle increment performance",
716 __FILE__, QAHandleInc, THE_GROUP);
717 theCommands.Add ("QAHandleCast",
718 "QAHandleCast [instance=50 [pointerTo=0 [nbIter=1000000]]]"
719 "\n\t\t: Test handle DownCast performance."
720 "\n\t\t: instance - specifies the depth of instantiated class"
721 "\n\t\t: pointerTo - specifies the depth of pointer class, where instance is stored into",
722 __FILE__, QAHandleCast, THE_GROUP);
723 theCommands.Add ("QAHandleKind",
724 "Test handle IsKind",
725 __FILE__, QAHandleKind, THE_GROUP);
726 theCommands.Add ("QAHandleOps",
727 "Test handle operations",
728 __FILE__, QAHandleOps, THE_GROUP);
729 return;
730}