From: Adriano d. S. F. <adr...@gm...> - 2010-01-30 18:54:24
|
We current compile with RTTI turned off, so dynamic_cast usage is not permitted. I see very good usages for it, as we convert legacy nodes to classes. Many places current need to check the nod_type (jrd and dsql). In my opinion, it's not good to convert things to classes and still maintain enums of types or introduce methods in the base classes and override to test for specific types. For example, DSQL node_match need to verify if they are equal. With C++ classes, the better way to do this is like: bool FunctionCallNode::match(ExprNode* other) { FunctionCallNode* o = dynamic_cast<FunctionCallNode*>(other); if (!o) return false; // test o and this properties } Is there a possibility that we move to real C++ in v3? Adriano |
From: Dimitry S. <sd...@ib...> - 2010-01-30 19:55:16
|
30.01.2010 19:54, Adriano dos Santos Fernandes wrote: > With C++ classes, the better way to do this is like: > > bool FunctionCallNode::match(ExprNode* other) > { > FunctionCallNode* o = dynamic_cast<FunctionCallNode*>(other); > if (!o) > return false; > > // test o and this properties > } > > Is there a possibility that we move to real C++ in v3? This move will require quite a few catches for bad_cast exception, no?.. -- SY, SD. |
From: Adriano d. S. F. <adr...@gm...> - 2010-01-30 20:05:33
|
Dimitry Sibiryakov wrote: > 30.01.2010 19:54, Adriano dos Santos Fernandes wrote: >> With C++ classes, the better way to do this is like: >> >> bool FunctionCallNode::match(ExprNode* other) >> { >> FunctionCallNode* o = dynamic_cast<FunctionCallNode*>(other); >> if (!o) >> return false; >> >> // test o and this properties >> } >> >> Is there a possibility that we move to real C++ in v3? > > This move will require quite a few catches for bad_cast exception, no?.. > No. bad_cast is thrown only when casting references, and the intended usage is for pointers. For pointers, NULL is returned when dynamic_cast "fail". Adriano |
From: Alexander P. <pes...@ma...> - 2010-01-31 11:35:07
|
On Saturday 30 January 2010 21:54:15 Adriano dos Santos Fernandes wrote: > We current compile with RTTI turned off, so dynamic_cast usage is not > permitted. > > I see very good usages for it, as we convert legacy nodes to classes. Many > places current need to check the nod_type (jrd and dsql). In my opinion, > it's not good to convert things to classes and still maintain enums of > types or introduce methods in the base classes and override to test for > specific types. > > For example, DSQL node_match need to verify if they are equal. > > With C++ classes, the better way to do this is like: > > bool FunctionCallNode::match(ExprNode* other) > { > FunctionCallNode* o = dynamic_cast<FunctionCallNode*>(other); > if (!o) > return false; > > // test o and this properties > } > > Is there a possibility that we move to real C++ in v3? I do not understand why do you call RTTI 'real C++'. I suggest you to use virtual functions instead, it's much better than keep casts in the code. |
From: Adriano d. S. F. <adr...@gm...> - 2010-01-31 14:05:40
|
Alexander Peshkoff wrote: > On Saturday 30 January 2010 21:54:15 Adriano dos Santos Fernandes wrote: >> We current compile with RTTI turned off, so dynamic_cast usage is not >> permitted. >> >> I see very good usages for it, as we convert legacy nodes to classes. Many >> places current need to check the nod_type (jrd and dsql). In my opinion, >> it's not good to convert things to classes and still maintain enums of >> types or introduce methods in the base classes and override to test for >> specific types. >> >> For example, DSQL node_match need to verify if they are equal. >> >> With C++ classes, the better way to do this is like: >> >> bool FunctionCallNode::match(ExprNode* other) >> { >> FunctionCallNode* o = dynamic_cast<FunctionCallNode*>(other); >> if (!o) >> return false; >> >> // test o and this properties >> } >> >> Is there a possibility that we move to real C++ in v3? > > I do not understand why do you call RTTI 'real C++'. I suggest you to use > virtual functions instead, it's much better than keep casts in the code. I call cutted C++ not real C++. C++ without its standard features. And I have a difficulty to understand why the compiler rejects dynamic_cast even exception handling depending on the *same* mechanics of it. Virtual functions is not the way to go for what dynamic_cast has invented for. Designing a set of classes with methods: virtual bool isFunctionCallNode() { return false; } virtual bool isEqualNode() { return false; } virtual bool isLiteralNode() { return false; } With specific overrides sucks. We may expect an enum entry in the base constructor, like current nod_type does. But I would still prefer to code the thing in C++, and not in Firebird-limited-C++ language. Adriano |
From: Alexander P. <pes...@ma...> - 2010-01-31 14:54:34
|
On Sunday 31 January 2010 16:37:42 Adriano dos Santos Fernandes wrote: > Alexander Peshkoff wrote: > > I do not understand why do you call RTTI 'real C++'. I suggest you to use > > virtual functions instead, it's much better than keep casts in the code. > > I call cutted C++ not real C++. C++ without its standard features. Not an argument - traditional C-cast is also standard deature, but we try to avoid and cleanup code from it. I see no reasons in redesigning DSQL code, if as the result we again have casts. > And I > have a difficulty to understand why the compiler rejects dynamic_cast even > exception handling depending on the *same* mechanics of it. > > Virtual functions is not the way to go for what dynamic_cast has invented > for. Agree :-) Provide an example, what for you need casts in new set of dsql node classes. > Designing a set of classes with methods: > > virtual bool isFunctionCallNode() { return false; } > virtual bool isEqualNode() { return false; } > virtual bool isLiteralNode() { return false; } > > With specific overrides sucks. > > We may expect an enum entry in the base constructor, like current nod_type > does. But I would still prefer to code the thing in C++, and not in > Firebird-limited-C++ language. I did not suggest to add _such_ virtual functions. A bit better approach is to continue with what already done like: virtual void genBlr() = 0; virtual DmlNode* pass1(thread_db* tdbb, CompilerScratch* csb) = 0; virtual DmlNode* pass2(thread_db* tdbb, CompilerScratch* csb) = 0; virtual jrd_nod* execute(thread_db* tdbb, jrd_req* request) const = 0; What need in casting with this approach? |
From: Adriano d. S. F. <adr...@gm...> - 2010-01-31 15:21:26
|
Alexander Peshkoff wrote: > > What need in casting with this approach? See for example node_match in pass1.cpp. I already provided that sample. It's different thing, expressions are more complicated than statements. We test nod_type in many places currently. And we still need to test specific node types when converting nodes to a class hierarchy. Dynamic cast is not a dumb cast like the others. It's the way to know if an expression is convertible to another, and fills the role of what we need. Let's say we have these classes: FunctionCallNode (abstract) UserFunctionCallNode : public FunctionCallNode SystemFunctionCallNode : public FunctionCallNode We may know if something is a generic function call or specific (user/system) calls. The same for aggregates: AggregateFunction (abstract) SumAggregateFunction : public AggregateFunction ... And we can test for generic aggregate functions (instead of current approach: case nod_agg_count: case nod_agg_average ...), and can still test for specific types (like when comparing if two nodes are equal). Making these things without dynamic_cast introduces unneeded and not better code. Adriano |
From: Alexander P. <pes...@ma...> - 2010-01-31 16:15:07
|
On Sunday 31 January 2010 18:21:17 Adriano dos Santos Fernandes wrote: > Alexander Peshkoff wrote: > > What need in casting with this approach? > > See for example node_match in pass1.cpp. I already provided that sample. > It's different thing, expressions are more complicated than statements. > > We test nod_type in many places currently. And we still need to test > specific node types when converting nodes to a class hierarchy. > > Dynamic cast is not a dumb cast like the others. It's the way to know if an > expression is convertible to another, and fills the role of what we need. > > Let's say we have these classes: > > FunctionCallNode (abstract) > UserFunctionCallNode : public FunctionCallNode > SystemFunctionCallNode : public FunctionCallNode > > We may know if something is a generic function call or specific > (user/system) calls. > > The same for aggregates: > AggregateFunction (abstract) > SumAggregateFunction : public AggregateFunction > ... > > And we can test for generic aggregate functions (instead of current > approach: case nod_agg_count: case nod_agg_average ...), and can still test > for specific types (like when comparing if two nodes are equal). > > Making these things without dynamic_cast introduces unneeded and not better > code. Do you know that dynamic_cast is rather slow operation? What about typeid/typeinfo, they are in no way better than existing enum. |
From: Adriano d. S. F. <adr...@gm...> - 2010-01-31 16:37:58
|
Alexander Peshkoff wrote: > On Sunday 31 January 2010 18:21:17 Adriano dos Santos Fernandes wrote: >> Alexander Peshkoff wrote: >>> What need in casting with this approach? >> See for example node_match in pass1.cpp. I already provided that sample. >> It's different thing, expressions are more complicated than statements. >> >> We test nod_type in many places currently. And we still need to test >> specific node types when converting nodes to a class hierarchy. >> >> Dynamic cast is not a dumb cast like the others. It's the way to know if an >> expression is convertible to another, and fills the role of what we need. >> >> Let's say we have these classes: >> >> FunctionCallNode (abstract) >> UserFunctionCallNode : public FunctionCallNode >> SystemFunctionCallNode : public FunctionCallNode >> >> We may know if something is a generic function call or specific >> (user/system) calls. >> >> The same for aggregates: >> AggregateFunction (abstract) >> SumAggregateFunction : public AggregateFunction >> ... >> >> And we can test for generic aggregate functions (instead of current >> approach: case nod_agg_count: case nod_agg_average ...), and can still test >> for specific types (like when comparing if two nodes are equal). >> >> Making these things without dynamic_cast introduces unneeded and not better >> code. > > Do you know that dynamic_cast is rather slow operation? > What about typeid/typeinfo, they are in no way better than existing enum. It could be slower than typeid, but relative to the hierarchy chain. Things like test for specific types could be done with typeid, and generic (base) ones with dynamic_cast. But that changes nothing in the discussion. We need RTTI for both features. Adriano |
From: Claudio V. C. <cv...@us...> - 2010-02-01 09:32:56
|
> -----Original Message----- > From: Adriano dos Santos Fernandes [mailto:adr...@gm...] > Sent: Sábado, 30 de Enero de 2010 15:54 > > We current compile with RTTI turned off, so dynamic_cast > usage is not permitted. It was decided years ago by Dmitry and others to get rid of RTTI in the code (I didn't have a strong preference). The idea was to use virtual functions and if the path required maximum performance, templates. C. |
From: Alexander P. <pes...@ma...> - 2010-02-01 09:52:36
|
On Monday 01 February 2010 12:43:22 Claudio Valderrama C. wrote: > > -----Original Message----- > > From: Adriano dos Santos Fernandes [mailto:adr...@gm...] > > Sent: Sábado, 30 de Enero de 2010 15:54 > > > > We current compile with RTTI turned off, so dynamic_cast > > usage is not permitted. > > It was decided years ago by Dmitry and others to get rid of RTTI in the > code (I didn't have a strong preference). The idea was to use virtual > functions and if the path required maximum performance, templates. As far as I understand, Adriano wants to discuss how reasonable was that decision. Initially suggestion to avoid RTTI came from Jim Starkey (in his very impressive manner). Most of us agreed with his mind that need in RTTI comes from bad style of programming. Must say that Adriano's suggestion to use RTTI to detect groups of nodes of similiar type shows that Jim was sooner of all wrong here. On the other hand, current code which enums required types of nodes and is using multiple cases to select needed group of nodes, is known to be efficient and fast. With dynamci_cast, which walks threw class ierarchy, this can't be guaranteed (it's known to be slower than switch operator). I see no problems walking threw class'es tree when error is thrown, but do not like when it's done during normal operation. May be we can stop making engine slower with ++ features? What about typeid/typeinfo - here really no performance questions asked. But how is it better than existing enum? |
From: Dmitry Y. <fir...@ya...> - 2010-02-01 10:42:25
|
Alexander Peshkoff wrote: > What about typeid/typeinfo - here really no performance questions asked. But > how is it better than existing enum? I suppose it could be considered better just because it allows to avoid those enums altogether :-) BTW, the performance issue re. dynamic_cast() vs typeid() is not that obvious, look at the test example here: http://www.devx.com/tips/Tip/5496 Then, we could limit RTTI usage to non-time-critical code paths only, e.g. say "yes" to the parser and "no" to the executor. Also, AFAIK, typeid() throws when used with dereferenced NULL pointers but this is a very common usage pattern in our code, so we'll have to ensure the every place using RTTI checks for NULLs beforehand. This looks too much error prone to me. But before making a decision, I'd prefer to see RTTI tested on all compilers / platforms we deal with. There maybe some unexpected surprises. Dmitry |
From: Claudio V. C. <cv...@us...> - 2010-02-01 12:07:54
|
> -----Original Message----- > From: Dmitry Yemanov [mailto:fir...@ya...] > Sent: Lunes, 01 de Febrero de 2010 7:42 > > Alexander Peshkoff wrote: > > > What about typeid/typeinfo - here really no performance > questions asked. But > > how is it better than existing enum? > > I suppose it could be considered better just because it > allows to avoid > those enums altogether :-) Dmitry, is this really an argument even as a joke? Enums may result to be more readable than a lot of calls to typeid. If the engine is separated in several dynamic libraries (as it seems the case for FB3), is typeid reliable? > Then, we could limit RTTI usage to non-time-critical code paths only, > e.g. say "yes" to the parser and "no" to the executor. If several nodes belong to the type "aggregation", they could inherit from an Aggregate node. A function that treats them generically will receive an Aggregate pointer. A function that requires some specific node will receive a pointer to that specific node type (assuming nodes continue to be converted into classes). As I said, I have no strong preference, but at the same time I don't see the need for typeid and typeinfo in the current code. It leads to SW that lacks elegance and in some cases (not all, of course) it's an indication of poor design. C. |
From: Alexander P. <pes...@ma...> - 2010-02-01 13:00:03
|
On Monday 01 February 2010 15:18:23 Claudio Valderrama C. wrote: > > -----Original Message----- > > From: Dmitry Yemanov [mailto:fir...@ya...] > > Sent: Lunes, 01 de Febrero de 2010 7:42 > > > > Alexander Peshkoff wrote: > > > What about typeid/typeinfo - here really no performance > > > > questions asked. But > > > > > how is it better than existing enum? > > > > I suppose it could be considered better just because it > > allows to avoid > > those enums altogether :-) > > Dmitry, is this really an argument even as a joke? Enums may result to be > more readable than a lot of calls to typeid. Agreed. And for sure faster. Typeid is complex (more or less) structure, it's faster to compare 2 integers than typeids. > If the engine is separated in > several dynamic libraries (as it seems the case for FB3), is typeid > reliable? Certainly not. At least in some posix environments. |
From: Adriano d. S. F. <adr...@gm...> - 2010-02-01 13:07:24
|
Alexander Peshkoff wrote: > > Agreed. And for sure faster. Typeid is complex (more or less) structure, it's > faster to compare 2 integers than typeids. > And for sure one can write everything in assembly and be faster than C++. >> If the engine is separated in >> several dynamic libraries (as it seems the case for FB3), is typeid >> reliable? > > Certainly not. At least in some posix environments. > Good non-sense argument, as at least for what I propose the thing is not to be used across libraries bondaries. But no problem... I can continue writing our crappy code way... I know how to code using enums... Let's not waste our time. Adriano |
From: Adriano d. S. F. <adr...@gm...> - 2010-02-01 13:22:12
|
Claudio Valderrama C. wrote: > > If several nodes belong to the type "aggregation", they could inherit from > an Aggregate node. A function that treats them generically will receive an > Aggregate pointer. A function that requires some specific node will receive > a pointer to that specific node type (assuming nodes continue to be > converted into classes). As I said, I have no strong preference, but at the > same time I don't see the need for typeid and typeinfo in the current code. > It leads to SW that lacks elegance and in some cases (not all, of course) > it's an indication of poor design. > Claudio, it looks like you're reading too much books of those people that never wrote a line of code. :-) The "design problem" is not with typeid or RTTI. As soon you create enums and do the same thing, your design is the same, and worse, you're recreating a pseudo language in your program. Generally, it's better to avoid these things, but you and anyone that write code knows that's not always possible or desired. Adriano |
From: Claudio V. C. <cv...@us...> - 2010-02-02 05:03:49
|
> -----Original Message----- > From: Adriano dos Santos Fernandes [mailto:adr...@gm...] > Sent: Lunes, 01 de Febrero de 2010 9:16 > > > Claudio, it looks like you're reading too much books of those > people that never > wrote a line of code. :-) I don't know which people you refer, but at least some people that write books on programming have participated in big projects. It may be informative to read sections about the authors of articles or books. Not all are like Codd. > The "design problem" is not with typeid or RTTI. As soon you > create enums and do > the same thing, your design is the same, Ok, but why is typeid better than an enum? > and worse, you're > recreating a pseudo > language in your program. Pseudo language? enums are part of the language same as RTTI. ;-) I want to see the advantages of typeid over enums when the real problem won't be solved as you said, because the design will be anyway non-optimal. But nobody explains the advantages. If I have a car with a failed engine, is it urgent to replace the old windows with polarized glass? I'm not against RTTI and I wasn't the one that disabled it, but I expect to be told what do we gain with reintroducing it. The same way, I wasn't the one that decided to wipe out the STL from the project, but since it was the agreement, I executed the agreement and cleaned isql to get rid of classes in the "std" namespace. > Generally, it's better to avoid these things, but you and > anyone that write code > knows that's not always possible or desired. Rsbs and their tags and enums were refactored into a class hierarchy. Not everything can be made to fit, but it's a good example. C. |
From: Alexander P. <pes...@ma...> - 2010-02-02 08:35:45
|
On Tuesday 02 February 2010 08:14:19 Claudio Valderrama C. wrote: > I want to see the advantages of typeid over enums when the real problem > won't be solved as you said, because the design will be anyway non-optimal. > But nobody explains the advantages. If I have a car with a failed engine, > is it urgent to replace the old windows with polarized glass? Adriano provided one sample - using dynamic_cast<> one can more reliably detect, is Node* ptr is actually pointer to AggregateNode. if (dynamic_cast<AggregateNode*>(ptr)) { // it's AggregateNode. } Currently used method: switch(ptr->node_type) { case nod_agg_average: case nod_agg_max: ....... // it's AggregateNode. break; } has this bad ...... - all kinds of AggregateNode should be mentioned here, and in case when we add new aggregate function, it should be added to all such places in the code. The question is - how often do we need to use such case sequences, which may be replaced by RTTI-based code? |
From: Claudio V. C. <cv...@us...> - 2010-02-02 09:49:25
|
> -----Original Message----- > From: Alexander Peshkoff [mailto:pes...@ma...] > Sent: Martes, 02 de Febrero de 2010 5:36 > > Adriano provided one sample - using dynamic_cast<> one can > more reliably > detect, is Node* ptr is actually pointer to AggregateNode. > > if (dynamic_cast<AggregateNode*>(ptr)) > { > // it's AggregateNode. > } > > Currently used method: > > switch(ptr->node_type) > { > case nod_agg_average: > case nod_agg_max: > ....... > // it's AggregateNode. > break; > } class AggregateNode {...}; class SumNode : public AggregateNode {...}; class AvgNode : public AggregateNode {...}; If there's a virtual function doSomething() in AggregateNode that's not pure virtual but it has the needed generic code, the SumNode::doSomething will call it and then will do its own specific work or may not need to call the generic code. Same for AvgNode and so on. Finally, the list of functions that process nodes by tag would be converted in a base node with several base functions that are overridden in the more specific node. Nothing new, right? Instead of nodes being sent to pass1 and pass2, each node class overrides the generic virtual functions pass1 and pass2. It may or may not be practical. Wasn't it done partially in DSQL already? > The question is - how often do we need to use such case > sequences, which may > be replaced by RTTI-based code? We would have to inspect the code and produce statistical data. :-) C. |
From: Alexander P. <pes...@ma...> - 2010-02-02 10:03:44
|
On Tuesday 02 February 2010 12:59:54 Claudio Valderrama C. wrote: > > -----Original Message----- > > From: Alexander Peshkoff [mailto:pes...@ma...] > > Sent: Martes, 02 de Febrero de 2010 5:36 > > > > Adriano provided one sample - using dynamic_cast<> one can > > more reliably > > detect, is Node* ptr is actually pointer to AggregateNode. > > > > if (dynamic_cast<AggregateNode*>(ptr)) > > { > > // it's AggregateNode. > > } > > > > Currently used method: > > > > switch(ptr->node_type) > > { > > case nod_agg_average: > > case nod_agg_max: > > ....... > > // it's AggregateNode. > > break; > > } > > class AggregateNode {...}; > class SumNode : public AggregateNode {...}; > class AvgNode : public AggregateNode {...}; > > If there's a virtual function doSomething() in AggregateNode that's not > pure virtual but it has the needed generic code, the > SumNode::doSomething will call it and then will do its own specific work or > may not need to call the generic code. Same for AvgNode and so on. Finally, > the list of functions that process nodes by tag would be converted in a > base node with several base functions that are overridden in the more > specific node. Nothing new, right? Instead of nodes being sent to pass1 and > pass2, each node class overrides the generic virtual functions pass1 and > pass2. It may or may not be practical. Wasn't it done partially in DSQL > already? Yes, certainly. Problems take place when 2 nodes should be analyzed simultaneously, like in node_match(). (Here I repeat what Adriano already wrote, just to make sure noone forgotten that samples.) But certainly _most_ of places, where one wants to analyze for group of nodes, are doable using virtual functions. |
From: Alexander P. <pes...@ma...> - 2010-02-02 14:49:26
|
On Tuesday 02 February 2010 16:27:16 Adriano dos Santos Fernandes wrote: > Alexander Peshkoff wrote: > > Yes, certainly. > > Problems take place when 2 nodes should be analyzed simultaneously, like > > in node_match(). (Here I repeat what Adriano already wrote, just to make > > sure noone forgotten that samples.) But certainly _most_ of places, where > > one wants to analyze for group of nodes, are doable using virtual > > functions. > > There is many places that compare nod_type. If you not use RTTI, you need a > way to know the "type". > > So I first asked for dynamic_cast, but what's more likely to be used is > typeid. It's just my preference to use dynamic_cast always, but if typeid > is faster I have no problem with it. > > We currently already have checks for NULL nodes, and node->nod_type is > already an error. So there is not a problem about this. > > I expect its usage to be at compilation phase only. If it's needed at > runtime (may be needed to evaluate aggregate and window functions, for > example) during the compilation that parts may be separated. Adriano, I anyway do not like typeid. When we talked about comparison with non-leaf class in deep tree using dynamic_cast, it had at least minimum sense. How and where typeid is better than enum I do not understand. But I know what problems it can create :-( For OSs, that do not support weak symbols (AIX and MacOS, latest has weak symbols, but support in g++ is broken), comparison of typeids in g++ is comparison of classes names using strcmp(). This is 'a bit' slower than comparison of 2 enums. BTW, probably same for windows - remember link given by Dmitry? http://www.devx.com/tips/Tip/5496 What will be with non-gcc/vc ports, only HP/IBM/SUN knows :-( What about particular HP c++ runtime, it made me crazy even w/o RTTI. Adriano, sorry, but looks like noone except you wants to change old decision not to use RTTI. Personally I do not want extra problems with non-linux port. |
From: Adriano d. S. F. <adr...@gm...> - 2010-02-02 13:27:27
|
Alexander Peshkoff wrote: > > Yes, certainly. > Problems take place when 2 nodes should be analyzed simultaneously, like in > node_match(). (Here I repeat what Adriano already wrote, just to make sure > noone forgotten that samples.) But certainly _most_ of places, where one > wants to analyze for group of nodes, are doable using virtual functions. > There is many places that compare nod_type. If you not use RTTI, you need a way to know the "type". So I first asked for dynamic_cast, but what's more likely to be used is typeid. It's just my preference to use dynamic_cast always, but if typeid is faster I have no problem with it. We currently already have checks for NULL nodes, and node->nod_type is already an error. So there is not a problem about this. I expect its usage to be at compilation phase only. If it's needed at runtime (may be needed to evaluate aggregate and window functions, for example) during the compilation that parts may be separated. Adriano |
From: Adriano d. S. F. <adr...@gm...> - 2010-02-02 16:48:52
|
Alex et al, If we can't turn RTTI on, I think we should make enums and classes associated in some way, so we shouldn't test for an enum and manually convert to its correspondent class. Follow a test that simulate what I mean. And to known things like "is the node an aggregate" would deserve some way to encode the types in a range of aggregates, use bit masks, or another similar solution. -------------------- #include <stdio.h> enum Type { TYPE_CLASS1, TYPE_CLASS2 }; class BaseClass { public: BaseClass(Type aType) : type(aType) { } public: template <typename T> T* as() { if (type == T::TYPE) return (T*) this; else return NULL; } template <typename T> bool is() { return type == T::TYPE; } public: Type type; }; template <Type type, typename T> class PoorRtti : public T { public: PoorRtti() : T(type) { } public: const static Type TYPE = type; }; class Class1 : public PoorRtti<TYPE_CLASS1, BaseClass> { public: }; class Class2 : public PoorRtti<TYPE_CLASS2, BaseClass> { public: }; int main() { Class1 c1a; Class1 c1b; Class2 c2a; Class2 c2b; printf("%d\n", c1a.type == c1b.type); printf("%d\n", c2a.type == c2b.type); printf("%d\n", c1a.type == c2a.type); printf("%d\n", c1a.type == c2a.type); printf("%d\n", c2a.type == c1b.type); printf("%d\n", c2a.type == c1b.type); printf("\n"); printf("%p, %p\n", c1a.as<Class1>(), c1b.as<Class1>()); printf("%p, %p\n", c2a.as<Class2>(), c2b.as<Class2>()); printf("%p, %p\n", c1a.as<Class2>(), c1b.as<Class2>()); printf("%p, %p\n", c2a.as<Class1>(), c2b.as<Class1>()); printf("\n"); printf("%d, %d\n", c1a.is<Class1>(), c1b.is<Class1>()); printf("%d, %d\n", c2a.is<Class2>(), c2b.is<Class2>()); printf("%d, %d\n", c1a.is<Class2>(), c1b.is<Class2>()); printf("%d, %d\n", c2a.is<Class1>(), c2b.is<Class1>()); } -------------------- Adriano |
From: Alexander P. <pes...@ma...> - 2010-02-03 14:18:32
|
On Tuesday 02 February 2010 19:48:47 Adriano dos Santos Fernandes wrote: > Alex et al, > > If we can't turn RTTI on, I think we should make enums and classes > associated in some way, so we shouldn't test for an enum and manually > convert to its correspondent class. > > Follow a test that simulate what I mean. And to known things like "is the > node an aggregate" would deserve some way to encode the types in a range of > aggregates, use bit masks, or another similar solution. OK for me, may except name PoorRtti. On the other hand - why not? :)) |
From: Dimitry S. <sd...@ib...> - 2010-02-02 09:44:27
|
02.02.2010 9:35, Alexander Peshkoff wrote: > switch(ptr->node_type) > { > case nod_agg_average: > case nod_agg_max: > ....... > // it's AggregateNode. > break; > } > > has this bad ...... - all kinds of AggregateNode should be mentioned here, and > in case when we add new aggregate function, it should be added to all such > places in the code. > > The question is - how often do we need to use such case sequences, which may > be replaced by RTTI-based code? Another question is: why we can't mode code from "it's AggregateNode" to method of AggregateNode class? -- SY, SD. |