POV-Ray : Newsgroups : povray.general : CSDL: C-like Simulation Description Language Server Time
7 Aug 2024 09:22:18 EDT (-0400)
  CSDL: C-like Simulation Description Language (Message 41 to 50 of 65)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Lutz Kretzschmar
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 17:54:53
Message: <tlfu4ugj6v0ucd2tsavdiq2ihbr15bu5e3@4ax.com>
Hi Warp, you recently wrote in povray.general:

> Thorsten Froehlich <tho### [at] trfde> wrote:
> : return new SubClass(*this);
> 
>   Uh. That hurts my eyes.
Why? That's the standard way of cloning an object (standard in the
sense of widely used). Simply invoke the copy constructor on the
current instance. How else would you write a Clone() or Copy()
function?

- Lutz
  email : lut### [at] stmuccom
  Web   : http://www.stmuc.com/moray


Post a reply to this message

From: Ron Parker
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 17:59:02
Message: <slrna4ug1q.3n5.ron.parker@fwi.com>
On Wed, 23 Jan 2002 17:54:07 -0500, Christopher James Huff wrote:
> In C++, if you have a derived object that implements a certain method 
> not in its base class, but only have a base-class pointer to it, you 
> can't call that method unless you cast to that type. It's a pain that 
> produces ugly code, that's all. In Objective C, the methods you can call 

Only if you let it.

Clearly Warp hasn't asked the right question.  The right question is, why
do you have a base-class pointer if you want a derived-class pointer?  

The reason for all this is pretty simple.  If all you have is a base-class 
pointer, how do you know that it's a pointer to an instance of the right 
derived class?  Without more information, you don't.  The cast is how you 
tell the compiler that it's all right, you've thought of that, and you 
really do want to do what you're doing.

--
#macro R(L P)sphere{L __}cylinder{L P __}#end#macro P(_1)union{R(z+_ z)R(-z _-z)
R(_-z*3_+z)torus{1__ clipped_by{plane{_ 0}}}translate z+_1}#end#macro S(_)9-(_1-
_)*(_1-_)#end#macro Z(_1 _ __)union{P(_)P(-_)R(y-z-1_)translate.1*_1-y*8pigment{
rgb<S(7)S(5)S(3)>}}#if(_1)Z(_1-__,_,__)#end#end Z(10x*-2,.2)camera{rotate x*90}


Post a reply to this message

From: Christopher James Huff
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 18:08:50
Message: <chrishuff-2A99E7.18095223012002@netplex.aussie.org>
In article <3c4f3723@news.povray.org>,
 "Thorsten Froehlich" <tho### [at] trfde> wrote:

> And you don't need to duplicate any code at all.  Simply make your copy
> function virtual.  That way by default the copy function of the subclass
> will be called.  In that function simply write "return new SubClass(*this);"
> and all your problems are gone.

That's what I do, that was the duplicate code I was talking about...I 
just get tired typing that stupid one-liner in every time, when a 
subclass only needs to change one method.


> > Having to return void pointers and cast them to the
> > correct types. Mostly having what I can do with an object being
> > determined by the type of pointer to it I have, instead of what the
> > object can do.
> Hmm, this really should not happen. 

Yeah, I can get around it, but the code's not really any better. I'm 
going to redesign that portion of the code to use templates and get rid 
of the void pointers for the next alpha...


> Well, keep in mind that the most powerful feature of templates, the "export"
> keyword is not supported in any compiler yet.  Once it will be available
> templates have a potential far greater than what i.e. Java offers for
> reusable containers.  Basically the export keyword has the power to
> completely delegate the choice of code reuse to the compiler.  Current
> compilers will duplicate a lot of similar code, and some will then hope for
> the linker to cleanup the mess.  Of course, this way a lot of potential
> using the available information for optimization is lost :-(

I'm not sure quite what you mean...though if no compilers support it 
yet, I guess it doesn't really matter.

-- 
 -- 
Christopher James Huff <chr### [at] maccom>


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 18:38:26
Message: <3c4f4972@news.povray.org>
In article <chr### [at] netplexaussieorg> , 
Christopher James Huff <chr### [at] maccom>  wrote:

> In C++, if you have a derived object that implements a certain method
> not in its base class, but only have a base-class pointer to it, you
> can't call that method unless you cast to that type. It's a pain that
> produces ugly code, that's all. In Objective C, the methods you can call
> are determined by what the object itself responds to, at runtime, not by
> the type of pointer you have.

Not really.  dynamic_cast<> does exactly the same, with the only difference
that you have the choice of the object you actually want to respond.  It
protects you from getting a pointer to a base and then calling some method
by accident also you never wanted to call that method of that object.  In
C++ you are protected from this because you have to explicitly say _what_
you want rather than having the system take a guess and possibly giving you
something you never asked for.

Most important, dynamic_cast<> is fully type-safe, which seems to be what
you are missing.  Further, it is significantly more efficient because you
only do the dynamic casting once (by casting the first time you need to
access that particular object and storing the it in a local pointer of the
correct type), while in Objective C, for repeated calls to various functions
the compiler would have to employ (nearly) impossible analysis of the code
to turn it into just one call.  Thus it has to run the dynamic casting code
every time, which is extremely inefficient.

Apart from this, without dynamic_cast<>, multiple inheritance would be far
more difficult to use.

    Thorsten

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 18:47:13
Message: <3c4f4b81@news.povray.org>
In article <chr### [at] netplexaussieorg> , 
Christopher James Huff <chr### [at] maccom>  wrote:

> They make my head hurt. ;-)
> They're fine unless there's a problem. If there's a problem, it's often
> very difficult to figure out what it is from the error messages. And the
> syntax looks like something just tacked onto the C language, but my
> complaint is mainly about the error messages they give. Fortunately,
> they haven't been causing me any trouble in CSDL...

Like these two (yes, *two*)?  The errors were so simple, I don't even
remember what they were, and I am not going to track them down from this
message again!

Error   : function call 'insert(std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>>)' does not match
'std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::list<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::allocator<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>>, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>>>>>::insert(const
std::pair<const std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::list<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::allocator<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>>> &)'
'std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::list<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::allocator<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>>, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>,
std::allocator<char>>>>>>>::insert(std::__tree<std::pair<const
std::basic_string<char, std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>>>,
std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::list<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::allocator<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>>, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>>>>>::value_compare,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>>>>>::iterator, const
std::pair<const std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::list<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::allocator<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>>> &)'
'std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::list<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::allocator<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>>, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>,
std::list<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, std::allocator<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>>>>>::insert<...>(T1_0, T1_0)'
povdocgen.cpp line 195   attributelists.insert(attribute, entries);


Error   : function call 'insert(std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor *)' does not match
'std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, Processor *, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor *>>>::insert(const
std::pair<const std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, Processor *> &)'
'std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, Processor *, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor
*>>>::insert(std::__tree<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor *>,
std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, Processor *, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor
*>>>::value_compare, std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor *>>>::iterator,
const std::pair<const std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, Processor *> &)'
'std::map<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>, Processor *, std::less<std::basic_string<char,
std::char_traits<char>, std::allocator<char>>>,
std::allocator<std::pair<const std::basic_string<char,
std::char_traits<char>, std::allocator<char>>, Processor
*>>>::insert<...>(T1_0, T1_0)'
povdocgen.cpp line 858   processors.insert(processor, this);



____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Warp
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 18:57:16
Message: <3c4f4ddc@news.povray.org>
Christopher James Huff <chr### [at] maccom> wrote:
: And how else am I supposed to get a copy?

  Needing to do this with just mere base class pointers is clear sign that
you haven't designed your object hierarchy well.

  For example in our project I have implemented a bitvector which has some
functionalities needed in our libraries that std::vector<bool> doesn't have,
and which implements the copy-on-write technique for efficiency (these
bitvectors are copied a lot and modified very seldom). (If you don't know
what the copy-on-write technique means, just ask.)
  It either allocates the bit array dynamically or uses a user-given memory
location (kind-of placement new functionality).
  Of course this is a very different situation than yours, but now I'm getting
to my point: Things are allocated dynamically, copied, freed and so on, but
all inside the bitvector class. The bitvector handles everything.
  From outside I only need to use instances of this bitvector. I can assign
this bitvector, give it as a value parameter, return it by value, everything
that can be done by value (ie, no pointers) and it still is efficient, no
matter how large the bitvector is. It itself takes care of everything related
to pointer and dynamic allocation *inside* itself, privately. I don't see what
it does from outside, and I don't even want to see it.
  That's the whole point of modularity.

  One of the main principles of modularity is that if a module reserves a
resource (eg. memory), the same module (moreover, with just a few exceptions,
the same instance of the module which made the allocation) takes care of
freeing this resource and that no leaks happen.
  A module which allocates a resource and then returns a handle to this
resource to the outside, to the upper level and *hopes* that it gets freed
somewhere else, is almost always a sign of a really, really bad module design.

  Designing a good, working and secure object hierarchy is not something to
be done lightly, not even in medium to small sized programs. If you make
a good design, you'll gain a lot later.

:> : Having to return void pointers and cast them to the 
:> : correct types.
:>   I never have to do this. It also breaks badly modular OO design.

: Which is why I don't like it.

  One of the reasons why so many people love Java and hate C++ is that
Java simply doesn't support "bad" features from C, while C++ does (for
compatibility). Usually people who learn C++ come from C, where they learnt
really bad habits, which they can't get rid of in C++ for long, long time
(unless they have very good teachers). The good thing in Java is that it just
doesn't have these bad ways of doing things, so you just can't use them.
  Personally I dislike Java because in my opinion it has gone just way too
far with its limitation of "bad" features (which really aren't). Java has
many good things, and many of the limitations are things that I don't really
miss (eg. "kludgy" pointer casts), but on the other hand it misses things
that are really useful in C++ and helps a lot in implementing modularity
(even though some of these things *might* be possible to use in a wrong way,
I don't, so removing them is a true limitation to me).

: In C++, if you have a derived object that implements a certain method 
: not in its base class, but only have a base-class pointer to it, you 
: can't call that method unless you cast to that type.

  I don't want to sound rude, but you should really study object orientedness
principles in more detail.
  In an object-oriented hierarchy a module/function which takes a base class
reference/pointer is only interested in the base class interface. It does
not know, and moreover it doesn't even want to know, if there's really a
derived class behind that reference or pointer. It just sees a base class
and period (the derived class *is a* base class by all practical means); it's
not interested in anything else.
  If this kind of module/function needs to know more, it's usually a sign
of bad OO design.

: I've been avoiding using references

  Bad idea. You should really use references instead of pointers whenever
possible (and *const* references whenever possible).
  It's much easier to shoot yourself in the foot with pointers than with
references.
  It's not a syntax thing (syntax is usually the least of your worries). It's
a higher level thing.

: And I have to use dynamic allocation because the objects are going to 
: stick around for an indefinite amount of time, they can't be deleted 
: when the function goes out of scope.

  That's where you should make a module (ie a class) to handle this and not
just leave the pointers float around and hope that they will sometime be
freed by something. That sounds a lot like what you want to do is a
container class (ie. a class that contains objects and takes care of creating
and destroying them).

:> : Templates.
:> 
:>   What about them?

: They make my head hurt. ;-)

  Templates are incredibly versatile. In fact, it has been proven that
templates (with C++ types) alone are a turing-strong language. You can
make loops, lists, trees, conditionals, etc. which are evaluated at
compilation time (ie. you can, for example, make a list of constant int
values, add values at the end of the list, remove values from the list,
join lists, traverse a list etc, all at compilation time).
  (This is actually a whole field of research, called "generative
programming".)

  Templates have saved me a lot of work in many places.

: They're fine unless there's a problem. If there's a problem, it's often 
: very difficult to figure out what it is from the error messages.

  Templates have their problems, and error messages are one of them (the
other is that no compiler yet has implemented export templates, which means
that your object files will be HUGE if you use lots of big templates).
  However, you get used to them with experience. (Also with experience you
just usually avoid the error messages completely :P )

-- 
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -


Post a reply to this message

From: Warp
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 19:05:22
Message: <3c4f4fc2@news.povray.org>
Lutz Kretzschmar <lut### [at] stmuccom> wrote:
: Why? That's the standard way of cloning an object (standard in the
: sense of widely used). Simply invoke the copy constructor on the
: current instance. How else would you write a Clone() or Copy()
: function?

  It may be a standard way in Java. In C++ it's a standard way of getting
sure that you will get a high chance of a memory leak (specially if there's
more than one person using the library which does that). (And no, the way
Java handles object allocation and freeing is not always good.)

  As I already said in another article, one of the basic principles of
modularity is that if a module (class, whatever) allocates a resource, the
same module takes care that the resource gets freed (and gets freed only
once).
  Making a module which allocates a resource, returns a handle to this
resource outside and hopes that someone else will hopefully free it somewhere,
is a *really* bad module design (and OO design).

  The whole class hierarchy should be designed so that this kind of copying
is not needed (ie. not in this way). This usually can be done much better
and much more nicely (and specially much more safely).
  Making efforts for a good design now can save you a lot of trouble later.

-- 
#macro N(D)#if(D>99)cylinder{M()#local D=div(D,104);M().5,2pigment{rgb M()}}
N(D)#end#end#macro M()<mod(D,13)-6mod(div(D,13)8)-3,10>#end blob{
N(11117333955)N(4254934330)N(3900569407)N(7382340)N(3358)N(970)}//  - Warp -


Post a reply to this message

From: Warp
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 19:11:30
Message: <3c4f5132@news.povray.org>
Thorsten Froehlich <tho### [at] trfde> wrote:
: Apart from this, without dynamic_cast<>, multiple inheritance would be far
: more difficult to use.

  I have used multiple inheritance. I haven't needed dynamic_cast<> (nor
any other cast for that matter).

  dynamic_cast<> is one of those casts which you just shouldn't use (ok,
not that; what I mean is that you should almost never use downcasting;
downcasting is generally bad).
  The other casts you should never use are const_cast<> (used just as a hack
for dealing with old bad-designed libraries) and reinterpret_cast<> (which
is mainly used for low-level hacking).

-- 
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 19:11:34
Message: <3c4f5136@news.povray.org>
In article <chr### [at] netplexaussieorg> , 
Christopher James Huff <chr### [at] maccom>  wrote:

> I'm not sure quite what you mean...though if no compilers support it
> yet, I guess it doesn't really matter.

Imagine

list<MyClassA> lista;
list<MyClassB> listb;

where MyClassA and MyClassB have no common base.

Compilers right now just copy the code for all functions.  Later the linker
will only strip unused functions, but that is all.

However, if the compiler collects the requirements (the misc operator member
functions, i.e. constructors, destructors, comparison operators) in advance,
it could exploit this advance knowledge.  For example then the function to
insert an element would be the same, it would only have to know what class
the user wishes to insert and then call the constructor of that class
dynamically.

To understand why this isn't possible without "export" is that the compiler
only looks at one translation unit (a source file) at a time.  The "export"
keyword basically tells the compiler that there is shared code.  Of course,
onyl could simply parse all translation units and treat them as one, but
doing so would require so much memory for a mid-sized project, we cannot
dream about for decades to come! *

    Thorsten

* Just imagine that with optimizations, CW needs over 100 MB of memory for
some source files in POV-Ray.  Now consider there are 100 of those files,
and you fill 5-10 GB quickly!  Of course, POV-Ray can be considered a
"small" project compared to most commercial applications these days...

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: CSDL alpha 1 release
Date: 23 Jan 2002 19:26:21
Message: <3c4f54ad@news.povray.org>
In article <3c4f3a4c@news.povray.org> , Warp <war### [at] tagpovrayorg>  wrote:

> Thorsten Froehlich <tho### [at] trfde> wrote:
> : return new SubClass(*this);
>
>   Uh. That hurts my eyes.

So I assume you don't read "The C++ Programming Language" from Stroustrup?

Well, at least you will have to stop reading it now that I direct your
attention to p. 424  (in the 3rd edition paperback of the book) aka section
15.6.2 "Virtual Constructors".  After all, you should really not hurt your
eyes intentionally! ;-)

    Thorsten

PS: I am sorry, but it looks like you lost this argument...

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.