Topic: implicit class std::object
Author: David R Tribble <david@tribble.com>
Date: 1999/08/04 Raw View
Darin Adler wrote:
>
> David R Tribble <david@tribble.com> wrote:
>
> > Probably. Since we're limiting implicit inheritance of std::object
> > to non-POD objects, i.e., to objects with a _vtbl, probably all of
> > the functions of class std::object should be pure virtual.
>
> The standard refers to a struct/class that defines or inherits at
> least one virtual function as a "polymorphic type" -- it's probably
> better to talk about that and stay away from the POD terminology.
Yes. Class std::object would only be implicitly inherited by
polymorphic types.
> There's no reason to declare a default constructor and copy
> constructor in your proposed std::object. A class without either
> can still be constructed and copied, so I don't see a benefit
> including them in the class definition.
You are correct.
> If you seriously intend to propose a std::object, It seems a bad idea
> to make any of its member functions pure virtual. If the functions
> are pure virtual it will then be an error to define any polymorphic
> type where you don't override them.
You are correct. The default base functions in std::object should
be provided, but should do very little.
-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: stanley@West.Sun.COM (Stanley Friesen [Contractor])
Date: 1999/08/04 Raw View
In article <7nsn3o$1edc@enews3.newsguy.com>,
Darin Adler <darin@bentspoon.com> wrote:
>(By the way, I don't know what a "UDT" is.)
User Defined Type. [just what it says: in C++ any class, struct or
enum type].
Pretty much a sine qua non of object-oriented programing.
[Along with polymorphism and inheritance].
>----------------
>
>I don't find the std::object proposal compelling. The two proposed features
>that I understand that I've seen proposed so far are:
>
> 1) Define new pointer type, a kind of limited void*, called
>std::object*. This new pointer can only point to a polymorphic type. This is
>considered cleaner than void*.
>
> 2) Define a pure virtual function, std::string toString() const, to be
>overridden in the definition of classes for all polymorphic types to provide
>a canonical string form of any object.
>
>I think it's appealing to have another kind of void* that's specifically
>designed for use with RTTI. I'm not sure it's important enough to add it,
>but it does seem that it would sometimes be useful. I don't think that this
>"implicit base class" is a particularly nice way to add it to the language.
>We should find another way.
I particularly dislike #2 above. It would require changing thousands of
existing classes for a very minute gain in capability.
Now, if the *compiler* generated the toString() function ... well *maybe*.
[I am still not all that enthralled with the idea, in some way it is just
a minimal wrapper around existing RTTI capabilities].
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/08/04 Raw View
Stan Brown wrote:
>
> I'm sorry, I seem to have a mental block in my POD, er head. I've
> never really grasped the POD concept, ...
Forget I said "POD types" in my original post. Replace it with
"non-polymorphic types", i.e., types with no virtual functions.
> Yes, I understand that you can use memcpy on an object that contains
> an ordinary pointer, but in practice you never would because then
> you'd have two pointers pointing to the same object, right?
void foo(const Bar *p);
void baz()
{
Bar obj;
Bar * a = &obj;
foo(a);
...
}
void foo(const Bar *p)
{
// At this point, both p and a point to obj!
p->func();
...
}
Not allowing two or more pointers to point to the same object would
also outlaw simple assignments:
Foo * p;
Foo * q;
q = p; // Uh oh! p and q point to the same Foo object!
p = new Foo;
-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/04 Raw View
In article <FFqq4B.qx@research.att.com>, ark@research.att.com (Andrew
Koenig) wrote:
> In article <MPG.120bd63d77659eca989dee@news.mindspring.com>,
> Stan Brown <brahms@mindspring.com> wrote:
>
> >I thought POD could also include pointers to built-in type or other POD
> >structs, and memcpy is not enough for copying them. Am I right or wrong
> >about that?
>
> Why do you think that memcpy is not enough for copying pointers?
I think it's a case of someone not differentiating between separate
concepts. For some reason, many people are confused by pointers, and thus
don't understand the basic (totally simple, IMO) concept. I assume these
people probably lump pointers and containment by reference together, and
thus consider pointers to be a special type, and not a built-in type just
like any other, with all the usual semantics. "Somehow the pointer has a
mind of its own and does something to what it points at." This type of
magical thinking will always leave the person at a loss when it comes to
using pointers.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/08/04 Raw View
In article <379e4223.47989837@news.csrlink.net>,
jpotter@falcon.lhup.edu (John Potter) wrote:
> On 27 Jul 99 00:53:38 GMT, David R Tribble <david@tribble.com> wrote:
> : I was recently thinking about how Java and other O-O languages
> : define all class types to inherit class 'Object' implicitly.
> : Comments?
> I have no reference for this; so, I will just say it:
> Java is Smalltalk in C++ clothing.
No. Java is actually excedingly close to EC++, as a language. It has a
limited form of multiple inheritance and garbage collection in plus, but
I don't see where that makes it particularly Smalltalk-like. (Because
it has C++-like static type checking, it needs the multiple inheritance,
whereas Smalltalk doesn't.)
What Java does have that C++ doesn't is a lot of libraries, some of
which require significant run-time support. One of those libraries
(reflection) *allows* extremely dynamic programming, a la Smalltalk.
But it is generally acknowledged that the use of this library should be
limited to special cases (debugging and program development tools, for
example).
> BS said something like:
> C++ is not the best Smalltalk. Smalltalk is the best Smalltalk.
So. David Tribbles point wasn't that Smalltalk has Object, so it must
be good. It was that Smalltalk, Java, Eiffel (plus quite a few others)
all have Object. So one is drawn to ask the question: why not C++? Did
all of the other language designers make a mistake, or is there
something unique in C++ which makes it not appropriate.
Historically, I'm tempted to say that the first suggestion is correct.
Programming evolves, and as little as five years ago, many people
probably felt the lack of Object in C++ as a problem: at any rate,
Microsoft apparently did (see CObject), and before them, one of the
first widespread class libraries (NIH something or other) also did.
Today, when I work in Java, I generally note that whenever an interface
involves Object, it was either poorly designed, or could be done better
if Java had templates.
--
James Kanze mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient e objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/08/04 Raw View
In article <37A2D903.6B31DD79@acm.org>,
Pete Becker <petebecker@acm.org> wrote:
>
> David R Tribble wrote:
> >
> > I was recently thinking about how Java and other O-O languages
> > define all class types to inherit class 'Object' implicitly. In the
> > case of Java, this provides some useful capabilities, such as the
> > fact that all objects have an overridable 'toString()' member
function,
> > and any type can be passed to a function as an argument of type
> > 'Object' (which seems a bit cleaner than 'void*').
> > So my question is, would it be useful if C++ did this, i.e., if all
> > class types [*] inherited class std::object implicitly?
Good question. The first thing to insist upon is the utility *in*
*C++*. The fact that other languages find it useful is not particularly
a proof. (The most frequent use in Java is in collections; in this
case, the C++ solution is templates is far superior.)
> > One problem, of course, is coming up with a useful definition of
> > the std::object class.
> That's the first question that ought to be considered. Before working
> out how to do it it's important to decide whether it's useful. If it
> isn't useful there's no need to discuss how to do it.
I think he did mention on potentially useful aspect. A lot of low level
framework functions use void*, as a means of handling a generic type.
While simple containers can easily be rewritten to handle things in a
typesafe manner, using templates, this is not always possible. In such
cases, an object* would have the advantage over void* of supporting a
typesafe dynamic cast on the extracting end.
This said, I'm still not totally convinced. Even in Java, many of the
better generic interfaces use a tagging interface (like Serializable, or
Remote), rather than just talking in terms of Object. Generally, to be
used at any interface, and object must adhere to a certain protocol.
Even if this protocol cannot easily be expressed in the form of pure
virtual functions in an abstract base class, I suspect that it is
generally useful to require that the programmer "declare" his intent, by
deriving from an abstract base class (which possibly only defines a
virtual destructor). Of course, the compiler won't be able to enforce
that the derived class actually conforms to the protocol, but this is
generally the case anyway: you can require that the derived class
implement the function x, but you can't enforce that the implementation
has the desired semantics.
> > namespace std
> > {
> > class object
> > {
> > // Does not have any data members
> > public:
> > virtual ~object();
> > object();
> > object(const object &r);
> >
> > // What other functions?
> >
> > // Perhaps...
> > string toString() const;
> > long int hash() const;
> > typeid_t * typeinfo() const;
> > };
> > }
IMHO: typeinfo is already handled by the keyword typeid -- I see no
further need. And I would put toString in a class Displayable, and hash
in a class Hashable (which should also require equals, or something
similar). Which only leaves the virtual destructor in object. (But as
I said, this *might* be useful in itself, since it allows effective use
of dynamic_cast.)
> What benefit is there from forcing all these functions on users? In
> Java, which sometimes elevates purity over practicality, this is
> necessary. For example, without toString, you can't write a generic
> output function. java.io.PrintStream.write(Object obj) calls
> obj.toString() to get a String to write into the stream. In C++ we use
> overloaded insertion operators.
Or use templates: one could easily imagine a template
template< class T >
ostream&
operator<<( ostream& dest , T const& obj )
{
obj.print( dst ) ;
}
In practice, for historical reasons, it generally works the other way
round. I use a template function which in turn invokes operator<<.
Still, I agree that the possibility of using overloaded global functions
(operators or no), combined with templates and application defined
tagging interfaces, probably covers 99.9% of the uses of Object in Java.
> Same thing for hash and typeinfo: you
> can write these as global functions when you need them without
imposing
> them on everyone.
Right.
If they are pure virtual, it is a pain, since everyone has to implement
them, even if they will never be called. And if they aren't pure
virtual, there's not much reasonable that the default implementation can
do. Java uses the physical address as the value in such cases. You can
output any Java object, without the programmer having done anything to
make it possible. But the output is just going to be a couple of
hexadecimal digits without any meaning to anyone.
This can actually be fun, at least if you have a masocistic streak. The
default renderers for cells in a table use toString. Someone puts the
wrong data type in a cell. What happens? No compiler error, no
run-time error, but a cell with some arbitrary output. Guess where the
error is.
IMHO, in such cases, a far better solution would be to define a
Displayable interface, with a pure virtual function toString. That way,
you can only output objects implementing the displayable interface, but
if an object implements this interface, the programmer has to provide
something. (Regretfully, there is no way for the base class to require
him to provide something reasonable.) Done this way, for example, an
attempt to put an inacceptable data type in a table cell should result
in a compile time error. (In fact, in this case, you'd probably want a
separate interface, Renderable, since it is possible to display objects
other than as a string -- an Icon is Renderable, even if its toString
method doesn't produce anything useful.)
Anyway, I think it is an idea worth studying, but I'd like to see some
concrete examples where it would make my life simpler before going any
farther.
--
James Kanze mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient=E9e objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/04 Raw View
In article <379F75AC.DC9BF2CB@tribble.com>,
David R Tribble <david@tribble.com> wrote:
> Eiffel has an implicitly inherited 'Object' class, and it supports
> multiple inheritance. (I think Smalltalk does, too.) Obviously,
> at least one language has solved the overhead problem. (Of course,
> Eiffel employs a smarter backend and linker than C++.)
Eiffel typically uses a C compiler for the back end. So the linker is
the same linker, and thus no smarter than what we use for C++.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/04 Raw View
In article <7nsn3o$1edc@enews3.newsguy.com>,
"Darin Adler" <darin@bentspoon.com> wrote:
> David R Tribble <david@tribble.com> wrote:
> I think it's appealing to have another kind of void* that's
specifically
> designed for use with RTTI. I'm not sure it's important enough to add
it,
> but it does seem that it would sometimes be useful. I don't think
that this
> "implicit base class" is a particularly nice way to add it to the
language.
> We should find another way.
How about something simple?
class object
{
public:
object(void *ptr) : ptr_(ptr) { }
virtual const type_info& typeid() const = 0;
template <class T>
T* cast()
{
if (typeid(T) == typeid())
return static_cast<T>(ptr_);
return 0;
}
};
template <class T>
class object_type : public object
{
public:
object_type(T* ptr) : object(ptr) { }
virtual const type_info() const { return typeid(T*); }
};
template <class T>
T object_cast(object p)
{
return p.cast<T>();
}
This was typed "free thought", so there's likely to be some errors
(both syntactical and logical), but you should get the general idea.
This can be used like this:
void func(object p)
{
my_obj obj* = object_cast<my_obj*>(p);
// ... Use obj* below
}
void caller()
{
my_obj obj;
func(object_type(&obj));
}
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: scorp@btinternet.com (Dave Harris)
Date: 1999/08/05 Raw View
david@tribble.com (David R Tribble) wrote:
> I was recently thinking about how Java and other O-O languages
> define all class types to inherit class 'Object' implicitly.
The main benefit in Java et al is that it enforces a protocol across all
vendors. Much of that benefit could come from adding a few protocol
classes to the standard library, and making inheritance from them
optional. Vendors will switch to the standard classes in due course.
There are some problems, notably to do with "diamond" repeated
inheritance, but these exist for your approach too. If they are to be
solved, I'd rather a general solution which worked for all pure abstract
base classes then a special case hack for std::object.
> string toString() const;
If toString() is virtual, it's quite hard for implementations to avoid
linking in std::string even if the function is never called. So if
obligatory, this seems to fall foul of the "don't pay for what you don't
use" criteria. I want to be able to use polymorphic types without linking
in std::string.
> typeid_t * typeinfo() const;
Why not use typeid?
> long int hash() const;
Hashing is kinda complicated. I'd rather not have to support a hashing
interface unless I have consciously elected to do so.
> virtual ~object();
This is good and is really all that is needed to ensure a polymorphic
class which supports a dynamically type-safe dynamic_cast<> and deletion.
Perhaps this is all that an optional std::object should contain.
Sometimes the things that go in "object", being things which all objects
support regardless of what they represent, actually belong in a
meta-object protocol.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/05 Raw View
In article <37A61D39.2533D6EE@tribble.com>, David R Tribble
<david@tribble.com> writes
>Not allowing two or more pointers to point to the same object would
>also outlaw simple assignments:
and, more importantly, the use of virtual function tables:)
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Bill Seymour <bsey@pobox.com>
Date: 1999/08/05 Raw View
David R Tribble wrote:
>
> Darin Adler wrote:
> >
> > If you seriously intend to propose a std::object, It seems
> > a bad idea to make any of its member functions pure virtual.
> > If the functions are pure virtual it will then be an error
> > to define any polymorphic type where you don't override them.
>
> You are correct. The default base functions in std::object
> should be provided, but should do very little.
>
This is what makes me suspicious of the std::object idea: it
assumes that all objects share some kind of minimal behavior,
then provides useless behavior for those objects where the
assumption turns out to be invalid. Java's Object.toString()
is a good example.
IMO, it makes it very difficult to explain to novices what
public inheritance is *supposed* to mean in principle when
counter-examples like Object.toString() are present in the
language itself and so appear to have some kind of authority.
--Bill Seymour
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/08/05 Raw View
sirwillard@my-deja.com wrote:
>
> In article <379F75AC.DC9BF2CB@tribble.com>,
> David R Tribble <david@tribble.com> wrote:
> > Eiffel has an implicitly inherited 'Object' class, and it supports
> > multiple inheritance. (I think Smalltalk does, too.) Obviously,
> > at least one language has solved the overhead problem. (Of course,
> > Eiffel employs a smarter backend and linker than C++.)
>
> Eiffel typically uses a C compiler for the back end. So the linker is
> the same linker, and thus no smarter than what we use for C++.
Yes, but the way the Eiffel language and it LACE tool are designed,
it is possible to optimize class layouts and function dispatch prior
to linking (since using LACE gives the tool total knowledge of all
of the classes used by a program); these kinds of optimizations are
not possible in typical implementations of C++. That's what I meant
by "smarter".
-- David R. Tribble, david@tribble.com --
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: stanley@West.Sun.COM (Stanley Friesen [Contractor])
Date: 1999/08/05 Raw View
In article <7o9cpj$a64$1@nnrp1.deja.com>,
<James.Kanze@dresdner-bank.com> wrote:
>
>No. Java is actually excedingly close to EC++, as a language. It has a
>limited form of multiple inheritance and garbage collection in plus, but
>I don't see where that makes it particularly Smalltalk-like.
Java has a universal base class (aka an Object class)? *That* is what
makes it particularly Smalltalk-like. Merely having this class tends
to promote a Smalltalk-like programing style.
>
>So. David Tribbles point wasn't that Smalltalk has Object, so it must
>be good. It was that Smalltalk, Java, Eiffel (plus quite a few others)
>all have Object. So one is drawn to ask the question: why not C++?
Type safety.
C++'s designers chose to leave out unconstrained genericity, as implemented
in Object, and go for guarenteed type safety (as much as possible). So,
instead of Object, C++ has templates, which maintain type safety, by being
a form of *constrained* genericity.
Now, if the *only* things one were allowed to do with a Object pointer or
reference were to dynamic_cast it back to its dynamic type, or an accessible
base class of its dynamic type, and copy it, it *might* be compatible with
type safety. [This is comparable to the rule for void pointers, which do
not allow any operation except casting to the original type and copying].
Of course, for this to work, it would only be the implicit base class for
polymorphic types (that is types with virtual functions). Other class types
could not be imnplicitly derived from it, as that would impose virtual
function overhead on all classes.
> Did
>all of the other language designers make a mistake, or is there
>something unique in C++ which makes it not appropriate.
The latter. C++ designers made a different choice on an engineering tradeoff.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sirwillard@my-deja.com
Date: 1999/08/06 Raw View
In article <37A0CD78.9D7CAC8@tribble.com>,
David R Tribble <david@tribble.com> wrote:
> Of course, we could allow the compiler to handle the inheritance of
> class std::object in special ways, since it would be known to the
> compiler as a special class anyway.
This would necessitate std::object being a "primitive" type. I'm not
sure this is the right idea, and I'm further not sure the name should
(or could) be in namespace std if it were made a primitive.
Really, the only thing you're buying with std::object is a "better
void*". This can be done without the use of a base class (as I pointed
out in another post on this thread). An object base class would only
lead to the "fragile base class" syndrome being forced onto everyone.
It causes more problems then it solves.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jpotter@falcon.lhup.edu (John Potter)
Date: 1999/07/31 Raw View
On 27 Jul 99 00:53:38 GMT, David R Tribble <david@tribble.com> wrote:
: I was recently thinking about how Java and other O-O languages
: define all class types to inherit class 'Object' implicitly.
: Comments?
I have no reference for this; so, I will just say it:
Java is Smalltalk in C++ clothing.
BS said something like:
C++ is not the best Smalltalk. Smalltalk is the best Smalltalk.
Maybe Java is a better Smalltalk, but C++ is not. It is a totally
different language. Compare the early C++ container libraries
which tried to simulate Smalltalk to STL for example.
John
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: brahms@mindspring.com (Stan Brown)
Date: 1999/08/01 Raw View
I'm sorry, I seem to have a mental block in my POD, er head. I've never
really grasped the POD concept, so I hope you'll forgive what are
probably some stupid follow-up questions. (I checked Stroustrup3, but
there are no entries "POD" in the index.)
darin@bentspoon.com (Darin Adler) wrote in comp.std.c++:
>Objects of POD type can include pointers to built-in types and other POD
>structs. However, memcpy can be used to copy them. The standard specifically
>says that you can use memcpy.
Yes, I understand that you can use memcpy on an object that contains an
ordinary pointer, but in practice you never would because then you'd have
two pointers pointing to the same object, right?
Looked at another way, what kind of object is there that you could *not*
copy using memcpy? Granted, with an object that has a virtual function
you're also copying the vtable (at least in MSVC++ 5.0), but is there
some reason why that's a problem conceptually?
> 3.9/2 states that copying the bytes of an object of POD type to an array
>of char and back with memcpy will restore the original value of the object.
I'm sure I'm missing something obvious, but I just can't picture any
object of which that would not be true. Can you give a simple example?
> 3.9/3 states that you can copy the value one object of POD type into
>another object of the same POD type with memcpy.
And here again, I'm lost. a, What object is there that you actually
cannot copy with memcpy? but 2, why does this matter since memcpy is the
wrong way to copy anything that contains a pointer?
--
Stan Brown, Oak Road Systems, Cleveland, Ohio, USA
http://www.mindspring.com/~brahms/
I don't need e-mail copies of posted follow-ups, but if you send
them PLEASE identify them as such.
My reply address is correct as is. The courtesy of providing a correct
reply address is more important to me than time spent deleting spam.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/01 Raw View
In article <MPG.120d26b7a06ba2f4989df6@news.mindspring.com>, Stan Brown
<brahms@mindspring.com> writes
>
>I'm sorry, I seem to have a mental block in my POD, er head. I've never
>really grasped the POD concept, so I hope you'll forgive what are
>probably some stupid follow-up questions. (I checked Stroustrup3, but
>there are no entries "POD" in the index.)
>
>darin@bentspoon.com (Darin Adler) wrote in comp.std.c++:
>>Objects of POD type can include pointers to built-in types and other POD
>>structs. However, memcpy can be used to copy them. The standard specifically
>>says that you can use memcpy.
>
>Yes, I understand that you can use memcpy on an object that contains an
>ordinary pointer, but in practice you never would because then you'd have
>two pointers pointing to the same object, right?
And that is not in itself wrong! What is an error is to have two
objects owning the same object. You have to realise that pointers can
be used to won dynamic resources, and simply to 'refer' to an object
that is managed otherwise. Granted that a reference member is usually
better for the latter.
Essentially you can use memcpy (correctly) if no part of the object
needs a ctor for correct construction. Another way of looking at this
is to say that no part of the object needs a dtor for correct cleanup.
The main motive for introducing the concept of a POD is to lay certain
constraints on C++ compilers so that C-style data structures and idioms
will work as intended. In simple terms, implementors may not do fancy
layout's etc. for a POD. The data structure must be exactly what you
would expect with no hidden extras or re-ordering of members.
>
>Looked at another way, what kind of object is there that you could *not*
>copy using memcpy? Granted, with an object that has a virtual function
>you're also copying the vtable (at least in MSVC++ 5.0), but is there
>some reason why that's a problem conceptually?
There is absolutely no need to copy a vtable, it is the pointer to
vtable that gets copied, which by the way is a simple example of a non-
owning pointer.
>
>> 3.9/2 states that copying the bytes of an object of POD type to an array
>>of char and back with memcpy will restore the original value of the object.
>
>I'm sure I'm missing something obvious, but I just can't picture any
>object of which that would not be true. Can you give a simple example?
>
>> 3.9/3 states that you can copy the value one object of POD type into
>>another object of the same POD type with memcpy.
>
>And here again, I'm lost. a, What object is there that you actually
>cannot copy with memcpy? but 2, why does this matter since memcpy is the
>wrong way to copy anything that contains a pointer?
You cannot correctly copy any object with an internal pointer with
memcpy. As for your second assertion, see above.
BTW the compiler generated copy ctor for a simple type (for example,
one where all the data are of fundamental types) may well use memcpy for
efficiency --
>
>
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/08/01 Raw View
brahms@mindspring.com (Stan Brown) writes:
>I'm sorry, I seem to have a mental block in my POD, er head. I've never
>really grasped the POD concept, so I hope you'll forgive what are
>probably some stupid follow-up questions. (I checked Stroustrup3, but
>there are no entries "POD" in the index.)
Suppose you have an object type defined in a C++ program, and you'd
like code written in C to have access to it. What types can safely
and portably be shared in C and C++ code? (We implicitly assume
a C compiler compatible with the C++ compiler.)
Certainly you can share the basic data types: integer, floating
point, pointers.
Certainly you cannot share a general C++ class in portable code,
since once you introduce C++ features, you might lose the ability
to express portably the layout of the class in C.
What about a struct or union definition that would also be valid
in C? We'd like to know that the size and layout of the type would
be the same in C and C++.
So the basic idea behind defining "Plain Old Data" was that you
could portably share objects of that type in C and C++ code. Part
of being able to share objects is that the definition of copying
such an object in C is equivalent to the C++ definition of copying
the object. If you pass an object to C code, and the C code
makes copies of it (passing or returning by value, for example)
the result better be the same as when C++ code makes copies.
The majority of the C++ committee felt that you should be able to
add some C++ features to a struct or union without altering its
POD status. For example, adding static members should not affect
class size, layout or copy semantics, so a POD object can have
static members.
>Yes, I understand that you can use memcpy on an object that contains an
>ordinary pointer, but in practice you never would because then you'd have
>two pointers pointing to the same object, right?
Irrelevant. The semantics of copying a pointer are the same
using memcpy as using copy-construction or copy-assignment.
Besides, if an object has a designated owner, you can have as
many pointers to it as you like.
>Looked at another way, what kind of object is there that you could *not*
>copy using memcpy?
If we take "could not copy" to mean "could not copy with defined
semantics", the answer is any object having a user-written
copy constructor or copy-assignment operator (taking into
account all of its subobjects).
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/08/02 Raw View
For compatibility with C code, C-like types are called out as POD types.
Objects of these POD types, "plain old data", can be manipulated in ways
that are not guaranteed to work on other types of objects. The standard
makes specific guarantees for objects of POD type about global object
initialization, about the data being stored in contiguous bytes, about the
offsetof macro working on a POD-struct, about some specific ways of
manipulating the object with memcpy, about using the type as a parameter
with the va_arg macro, and about using reinterpret_cast to convert a pointer
to a POD-struct to a pointer to its first member, among others.
Non-POD types don't come with any of these guarantees.
Stan Brown <brahms@mindspring.com> wrote:
> Yes, I understand that you can use memcpy on an object that contains an
> ordinary pointer, but in practice you never would because then you'd have
> two pointers pointing to the same object, right?
I often have programs with two pointers pointing to the same object. If you
don't like to do that, it's a design rule, not a language rule. Are you
saying there's something wrong with this code?
int x;
int* p1(&x);
int* p2(p1);
After this sequence, both p2 and p1 point to the same object. It's an
application question whether you want have more than one pointer to a
particular object; the standard allows it (of course).
The POD/memcpy clauses in the standard say that the third line of the above
can be replaced by:
int* p2;
std::memcpy(&p2, &p1, sizeof(int*));
And it's guaranteed to have the same effect.
If you have pointers semantics where you want to have a single owner for
each pointer, you'll probably end up defining constructors or destructors or
using a pointer class with a constructor or destructor. Thus, your object
won't have POD type. It's undefined what happens if some code uses memcpy on
your object. If there's a constructor or destructor in the class itself or
in any of the non-static data members, then your class is not a POD type.
> Looked at another way, what kind of object is there that you could *not*
> copy using memcpy? Granted, with an object that has a virtual function
> you're also copying the vtable (at least in MSVC++ 5.0), but is there
> some reason why that's a problem conceptually?
The issue isn't whether memcpy might sometimes work, but whether users of
the language have a guarantee that they can use memcpy to copy an object and
it will always work.
The standard gives the compiler the freedom to lay out non-POD-type objects
with bytes that are not contiguous. It also gives it the freedom to do
things that wouldn't work with a raw-byte copy. The POD concept is there so
it so that clauses can be included for C compatibility. Since these clauses
only apply to objects with POD type, they leave the implementation less
constrained about the implementation of other objects.
Here's a contrived example: A particular C++ implementation might keep a
count in each virtual table of the number of objects of each class and
convert the virtual table into a unusable but more compact form when there
are no objects of that class and reconstitute it when objects of the class
exist once more. If copying objects with memcpy was allowed, this feature
would not work.
Here's another equally-contrived example: A C++ implementation might store
an offset from the object to the virtual table instead of using a pointer.
When copying an object, it can adjust the offset as necessary. A memcpy of
the object would not be able to do the adjustment.
I can come up with other examples, perhaps even some more-realistic ones, if
these examples don't make the principle clear.
>> 3.9/2 states that copying the bytes of an object of POD type to an array
>>of char and back with memcpy will restore the original value of the object.
> I'm sure I'm missing something obvious, but I just can't picture any
> object of which that would not be true. Can you give a simple example?
#include <string>
std::string o;
char a[sizeof(o)];
If you copy the bytes of object o into array a with memcpy, then modify
object o, then copy the bytes from array a back with memcpy, object o won't
necessarily have its original value. In fact, if you do this, the standard
provides no guarantees at all about what your program will do!
>> 3.9/3 states that you can copy the value one object of POD type into
>>another object of the same POD type with memcpy.
> And here again, I'm lost. a, What object is there that you actually
> cannot copy with memcpy? but 2, why does this matter since memcpy is the
> wrong way to copy anything that contains a pointer?
1) I hate to be pedantic, but the standard makes no guarantees about
whether your program will work if you copy *any* object of non-POD type with
memcpy. In practice, people creating compilers don't go out of their way to
ensure that memcpy doesn't work, but the standard does not make any
guarantees in these cases. It does make a guarantee for objects of POD type,
which constrains the compiler implementation to make sure that simple byte
copies will work for these simple objects.
b) memcpy has well-defined semantics for copying a pointer. You may
choose to avoid copying pointers in your programs, but the standard defines
exactly what will happen if you do copy a pointer, either with assignment or
with memcpy. What memcpy does on an object that is not of POD type is
undefined. The standard does not define what will happen if you copy an
object not of POD type with memcpy, but it does define what will happen if
you copy it with assignment.
-- Darin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/27 Raw View
I was recently thinking about how Java and other O-O languages
define all class types to inherit class 'Object' implicitly. In the
case of Java, this provides some useful capabilities, such as the
fact that all objects have an overridable 'toString()' member function,
and any type can be passed to a function as an argument of type
'Object' (which seems a bit cleaner than 'void*').
So my question is, would it be useful if C++ did this, i.e., if all
class types [*] inherited class std::object implicitly?
[*] To eliminate the overhead for POD types, we would restrict the
implicit inheritance to only classes having one or more virtual
member functions (i.e., types having a _vtbl). (Languages like Java
don't have POD class types because all member functions are implicitly
virtual, meaning that all objects have a hidden _vtbl-like element;
this explains why all Java classes can inherit class 'Object'
cheaply.)
One problem, of course, is coming up with a useful definition of
the std::object class.
namespace std
{
class object
{
// Does not have any data members
public:
virtual ~object();
object();
object(const object &r);
// What other functions?
// Perhaps...
string toString() const;
long int hash() const;
typeid_t * typeinfo() const;
};
}
Without any useful member functions, all that this buys us is the
ability to pass objects around as arbitrary 'object' types instead
of 'void*' types:
#include <object> // Declares class std::object
void foo(std::object *p)
{
bar(p);
KnownType * kt = static_cast<KnownType *>(p);
baz(kt);
}
Comments? (Stroustrup talks a little about an 'Object' class and
its drawbacks in C++PL 3E 16.2.2.)
-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/07/27 Raw View
In article <379CEBF8.7582F1E@tribble.com>, David R Tribble
<david@tribble.com> wrote:
> I was recently thinking about how Java and other O-O languages
> define all class types to inherit class 'Object' implicitly.
Isn't that tacky? Monolithic hierarchies, here we come.
> In the
> case of Java, this provides some useful capabilities, such as the
> fact that all objects have an overridable 'toString()' member function,
> and any type can be passed to a function as an argument of type
> 'Object' (which seems a bit cleaner than 'void*').
>
> So my question is, would it be useful if C++ did this, i.e., if all
> class types [*] inherited class std::object implicitly?
What happens here?
struct A {
virtual ~A();
};
struct B {
virtual ~B();
};
struct C : A, B { };
Do the types implicitly derived virtually from std::object? Nice overhead there.
[snip comment about PODs not having it as a base]
> One problem, of course, is coming up with a useful definition of
> the std::object class.
>
> namespace std
> {
> class object
> {
> // Does not have any data members
> public:
> virtual ~object();
> object();
> object(const object &r);
>
> // What other functions?
>
> // Perhaps...
> string toString() const;
> long int hash() const;
> typeid_t * typeinfo() const;
Shouldn't the first two be (pure?) virtual?
> };
> }
>
> Without any useful member functions, all that this buys us is the
> ability to pass objects around as arbitrary 'object' types instead
> of 'void*' types:
>
> #include <object> // Declares class std::object
>
> void foo(std::object *p)
> {
> bar(p);
>
> KnownType * kt = static_cast<KnownType *>(p);
> baz(kt);
> }
This would have the beneficial effect of allowing casts from untyped
pointers to be more safe, because you wouldn't use a void* anymore, but an
object*, so you wouldn't have the error of converting a Derived* to the
untyped pointer, then to Base* (if this were done with a void*, the
results would be undefined, while it would work correctly for object*).
> Comments? (Stroustrup talks a little about an 'Object' class and
> its drawbacks in C++PL 3E 16.2.2.)
I just don't see what could be universal. I think that even
type_info::name() is excessive, as that can add lots of overhead for the
names for deeply-nested template base classes and such. Of course, an
implementation can allow the user to specify that type_info::name() for
certain types returns a null string (which, I believe, is allowed by the
standard as type_info::name()'s return string is implementation-defined).
Would it be so hard for types that this would be useful on derive from a
common object class (as is done in many libraries currently)?
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Biju Thomas <b_thomas@ibm.net>
Date: 1999/07/27 Raw View
David R Tribble wrote:
>
> I was recently thinking about how Java and other O-O languages
> define all class types to inherit class 'Object' implicitly. In the
> case of Java, this provides some useful capabilities, such as the
> fact that all objects have an overridable 'toString()' member function,
> and any type can be passed to a function as an argument of type
> 'Object' (which seems a bit cleaner than 'void*').
>
[...]
>
> Comments?
How will it handle cases of multiple inheritance without the overhead of
virtual inheritance? Java (and Smalltalk?) doesn't face that problem.
--
Biju Thomas
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/07/30 Raw View
In article <slrn7ps7a6.kla.sbnaran@noname.nodomain.nowhere>,
sbnaran@uiuc.edu wrote:
> On 27 Jul 99 00:53:38 GMT, David R Tribble <david@tribble.com> wrote:
>
> >I was recently thinking about how Java and other O-O languages
> >define all class types to inherit class 'Object' implicitly. In the
> >case of Java, this provides some useful capabilities, such as the
> >fact that all objects have an overridable 'toString()' member function,
> >and any type can be passed to a function as an argument of type
> >'Object' (which seems a bit cleaner than 'void*').
> >
> >So my question is, would it be useful if C++ did this, i.e., if all
> >class types [*] inherited class std::object implicitly?
>
> I don't think this would be a good idea as it lowers type safety.
> Consider: In current C++ we can have a hierarchy of Animals -- eg,
> Goat Sheep Lion all derived from the most base class Animal. And
> we can have a hierarchy of Shapes -- eg, Rectangle Circle Ellipse
> all derived from the most base class Shape. Lots of other
> examples. And the type Animal* (which is basically an Animal
> object) is distinct from the type Shape* (which is basically a
> Shape object). But making a common base class std::object would
> make all objects (or all polymorphic objects) essentially
> equivalent. This is a blow to strong type safety.
By this same argument, void* is a "blow to strong type safety", but we
know that isn't the case. Casts are the main way to violate strict type
safety. The same would apply to a base class object.
Sorry, try again :-)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/30 Raw View
blargg wrote:
>
> David R Tribble <david@tribble.com> wrote:
> > One problem, of course, is coming up with a useful definition of
> > the std::object class.
> >
> > namespace std
> > {
> > class object
> > {
> > // Does not have any data members
> > public:
> > virtual ~object();
> > object();
> > object(const object &r);
> >
> > // What other functions?
> >
> > // Perhaps...
> > string toString() const;
> > long int hash() const;
> > typeid_t * typeinfo() const;
> > };
> > }
>
> Shouldn't the first two be (pure?) virtual?
Probably. Since we're limiting implicit inheritance of std::object
to non-POD objects, i.e., to objects with a _vtbl, probably all of
the functions of class std::object should be pure virtual.
-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Robert Piotter" <piotter@aesop.de>
Date: 1999/07/30 Raw View
>> >all of the _vtbls in all of the non-POD classes in a program would
>functions, i.e., only UDTs already having a _vtbl. I would
>specifically exclude POD types from implicitly inheriting
What does POD / UDT stand for?
Robert
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/07/30 Raw View
In article <7nsbdi$5s6$1@news.pop-stuttgart.de>, Robert Piotter
<piotter@aesop.de> writes
>What does POD / UDT stand for?
Plain Old Data Type (in simple terms they can be copied with memcpy) and
User Defined Type.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: brahms@mindspring.com (Stan Brown)
Date: 1999/07/30 Raw View
francis@robinton.demon.co.uk (Francis Glassborow) wrote in comp.std.c++:
>Plain Old Data Type (in simple terms they can be copied with memcpy) and
>User Defined Type.
I thought POD could also include pointers to built-in type or other POD
structs, and memcpy is not enough for copying them. Am I right or wrong
about that?
I've looked in the standard for a definition of POD, but I've never been
able to find it. Can someone point it out, and then I'll write it into
the index in my copy.
--
Stan Brown, Oak Road Systems, Cleveland, Ohio, USA
http://www.mindspring.com/~brahms/
I don't need e-mail copies of posted follow-ups, but if you send
them PLEASE identify them as such.
My reply address is correct as is. The courtesy of providing a correct
reply address is more important to me than time spent deleting spam.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/07/30 Raw View
brahms@mindspring.com (Stan Brown) writes:
>francis@robinton.demon.co.uk (Francis Glassborow) wrote in comp.std.c++:
>>Plain Old Data Type (in simple terms they can be copied with memcpy) and
>>User Defined Type.
>I thought POD could also include pointers to built-in type or other POD
>structs, and memcpy is not enough for copying them. Am I right or wrong
>about that?
I think what Francis meant was that memcpy would have the same
semantics for the object as assignment or initialization. That
is, for exammple, given POD objects o1 and o2 of the same type,
the operations
memcpy(o2, o1, sizeof(o2));
o2 = o1;
will have the same semantics. Consider
struct S { char* p; };
Although S contains a pointer, assigning one S to another has
the same semantics as copying with memcpy.
If an object (or a subobject) has user-defined constructors or
copy-assignment, assignment or initialization would not in general
have the same semantics as using memcpy.
(You can't use memcpy to intialize anything, but passing a
parameter by value in C is roughly equivalent to copying
it with memcpy, and passing by value is initialization.)
But that isn't the definition of POD, although the term was
invented to describe types that can be used the same way in C
and C++, loosely speaking. One consequence of the definition of POD
objects is that the way they are assigned or passed by value in
C will work for a C++ POD object. You can then expect to share
a POD object in C and C++ code.
>I've looked in the standard for a definition of POD, but I've never been
>able to find it. Can someone point it out, and then I'll write it into
>the index in my copy.
Clause 9, paragraph 4. It refers you to the definition of "aggregate"
in 8.5.1, which is needed to get the complete definition of POD.
--
Steve Clamage, stephen.clamage@sun.com
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/07/30 Raw View
Stan Brown <brahms@mindspring.com> wrote:
> I thought POD could also include pointers to built-in type or other POD
> structs, and memcpy is not enough for copying them. Am I right or wrong
> about that?
Objects of POD type can include pointers to built-in types and other POD
structs. However, memcpy can be used to copy them. The standard specifically
says that you can use memcpy.
> I've looked in the standard for a definition of POD, but I've never been
> able to find it. Can someone point it out, and then I'll write it into
> the index in my copy.
Here are some useful paragraphs of the standard:
3.9/10 defines "POD type"; that definition relies on the definitions of
"POD-struct" and "POD-union", among others.
9/4 defines "POD-struct" and "POD-union"; those definitions rely on the
definition of "aggregate", among others.
8.5.1/1 defines "aggregate".
3.9/2 states that copying the bytes of an object of POD type to an array
of char and back with memcpy will restore the original value of the object.
3.9/3 states that you can copy the value one object of POD type into
another object of the same POD type with memcpy.
-- Darin
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/07/31 Raw View
David R Tribble <david@tribble.com> wrote:
> Probably. Since we're limiting implicit inheritance of std::object
> to non-POD objects, i.e., to objects with a _vtbl, probably all of
> the functions of class std::object should be pure virtual.
Robert Piotter <piotter@aesop.de> wrote:
> What does POD / UDT stand for?
----------------
A caution about terminology:
The standard refers to a struct/class that defines or inherits at least one
virtual function as a "polymorphic type" -- it's probably better to talk
about that and stay away from the POD terminology. POD, "plain old data" for
people who haven't encountered the term before, is a lot more restrictive.
(By the way, I don't know what a "UDT" is.)
Non-POD is not quite the same thing as a struct/class with a virtual
function. You can have no virtual functions and still not qualify as a POD.
For example, if a class has a non-static member that is a pointer-to-member,
a non-POD struct, class, or union, or a reference, then it's not a POD. If
it has a user-defined copy constructor or destructor, it's not a POD.
In other words, it's not enough to say that POD classes won't automatically
inherit from your "std::object"; there are plenty of non-POD classes that
don't "have virtual tables", like instantiations of the "pair" template in
the standard library, for example.
Stay away from the "POD" in this discussion to be more precise.
Relevant paragraphs in the standard:
3.9/10 defines "POD type".
9/4 defines "POD-struct" and "POD-union".
10.3/1 defines "polymorphic class".
----------------
There's no reason to declare a default constructor and copy constructor in
your proposed std::object. A class without either can still be constructed
and copied, so I don't see a benefit including them in the class definition.
If you seriously intend to propose a std::object, It seems a bad idea to
make any of its member functions pure virtual. If the functions are pure
virtual it will then be an error to define any polymorphic type where you
don't override them. Thus every class with a virtual table will have to
provide or inherit an implementation of toString(), hash(), typeInfo().
Perhaps there's a misunderstanding about the term "pure virtual function"? I
am using the definition from the standard, section 10.4 [class.abstract].
----------------
I don't find the std::object proposal compelling. The two proposed features
that I understand that I've seen proposed so far are:
1) Define new pointer type, a kind of limited void*, called
std::object*. This new pointer can only point to a polymorphic type. This is
considered cleaner than void*.
2) Define a pure virtual function, std::string toString() const, to be
overridden in the definition of classes for all polymorphic types to provide
a canonical string form of any object.
I think it's appealing to have another kind of void* that's specifically
designed for use with RTTI. I'm not sure it's important enough to add it,
but it does seem that it would sometimes be useful. I don't think that this
"implicit base class" is a particularly nice way to add it to the language.
We should find another way.
I don't find it appealing to build in the concept of a string form for
objects of all polymorphic types into the language. I have many classes
where there really isn't a suitable string format that I want to define;
questions like "How brief?" and "How will this be used?" keep getting in the
way. And many of the objects which others would want to have in string form
are not polymorphic types!
People who do like having a string form for every object might want to
consider the way that the existing C++ streams facility helps. It provides a
standard way to do this. You can write toString() something like this:
#include <sstream>
template <class T> std::string toString(const T& object)
{
std::ostringstream stream;
stream << object;
return stream.str();
}
Individual classes implement their string form by overriding the stream
inserter operator.
----------------
Another matter of taste (mine): I'd prefer it if further discussion was
about specific functions that people want/advocate, and why std::object
would be a good/bad way to implement them, rather than about why std::object
is "bad taste" or "impossible". Any message that's just "pro" or just "con"
is more difficult for me to understand.
-- Darin
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Pete Becker <petebecker@acm.org>
Date: 1999/07/31 Raw View
David R Tribble wrote:
>
> I was recently thinking about how Java and other O-O languages
> define all class types to inherit class 'Object' implicitly. In the
> case of Java, this provides some useful capabilities, such as the
> fact that all objects have an overridable 'toString()' member function,
> and any type can be passed to a function as an argument of type
> 'Object' (which seems a bit cleaner than 'void*').
>
> So my question is, would it be useful if C++ did this, i.e., if all
> class types [*] inherited class std::object implicitly?
>
> One problem, of course, is coming up with a useful definition of
> the std::object class.
That's the first question that ought to be considered. Before working
out how to do it it's important to decide whether it's useful. If it
isn't useful there's no need to discuss how to do it.
>
> namespace std
> {
> class object
> {
> // Does not have any data members
> public:
> virtual ~object();
> object();
> object(const object &r);
>
> // What other functions?
>
> // Perhaps...
> string toString() const;
> long int hash() const;
> typeid_t * typeinfo() const;
> };
> }
>
What benefit is there from forcing all these functions on users? In
Java, which sometimes elevates purity over practicality, this is
necessary. For example, without toString, you can't write a generic
output function. java.io.PrintStream.write(Object obj) calls
obj.toString() to get a String to write into the stream. In C++ we use
overloaded insertion operators. Same thing for hash and typeinfo: you
can write these as global functions when you need them without imposing
them on everyone.
--
Pete Becker
Dinkumware, Ltd.
http://www.dinkumware.com
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/07/31 Raw View
blargg wrote:
....
> By this same argument, void* is a "blow to strong type safety", but we
> know that isn't the case.
?
'void *' is the prototypical example of the worst possible blow to type
safety. It's a practical necessity, and an improvement for some
purposes over 'char *', but don't ever make the mistake of assuming it's
safe. Every time you see a 'void *' in a piece of code, care is needed
to make sure it gets converted only to a pointer of the right type.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@noname.nodomain.nowhere (Siemel Naran)
Date: 1999/07/28 Raw View
On 27 Jul 99 00:53:38 GMT, David R Tribble <david@tribble.com> wrote:
>I was recently thinking about how Java and other O-O languages
>define all class types to inherit class 'Object' implicitly. In the
>case of Java, this provides some useful capabilities, such as the
>fact that all objects have an overridable 'toString()' member function,
>and any type can be passed to a function as an argument of type
>'Object' (which seems a bit cleaner than 'void*').
>
>So my question is, would it be useful if C++ did this, i.e., if all
>class types [*] inherited class std::object implicitly?
I don't think this would be a good idea as it lowers type safety.
Consider: In current C++ we can have a hierarchy of Animals -- eg,
Goat Sheep Lion all derived from the most base class Animal. And
we can have a hierarchy of Shapes -- eg, Rectangle Circle Ellipse
all derived from the most base class Shape. Lots of other
examples. And the type Animal* (which is basically an Animal
object) is distinct from the type Shape* (which is basically a
Shape object). But making a common base class std::object would
make all objects (or all polymorphic objects) essentially
equivalent. This is a blow to strong type safety.
>[*] To eliminate the overhead for POD types, we would restrict the
>implicit inheritance to only classes having one or more virtual
>member functions (i.e., types having a _vtbl). (Languages like Java
>don't have POD class types because all member functions are implicitly
>virtual, meaning that all objects have a hidden _vtbl-like element;
>this explains why all Java classes can inherit class 'Object'
>cheaply.)
Fine.
>One problem, of course, is coming up with a useful definition of
>the std::object class.
There are infinitely many useful definitions, and we shouldn't choose
one over the other.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Volker Denneberg <denne@aps.rwth-aachen.de>
Date: 1999/07/28 Raw View
David R Tribble wrote:
>
> I was recently thinking about how Java and other O-O languages
> define all class types to inherit class 'Object' implicitly. In the
> case of Java, this provides some useful capabilities, such as the
> fact that all objects have an overridable 'toString()' member function,
> and any type can be passed to a function as an argument of type
> 'Object' (which seems a bit cleaner than 'void*').
>
> So my question is, would it be useful if C++ did this, i.e., if all
> class types [*] inherited class std::object implicitly?
>
> [*] To eliminate the overhead for POD types, we would restrict the
> implicit inheritance to only classes having one or more virtual
> member functions (i.e., types having a _vtbl). (Languages like Java
> don't have POD class types because all member functions are implicitly
> virtual, meaning that all objects have a hidden _vtbl-like element;
> this explains why all Java classes can inherit class 'Object'
> cheaply.)
>
> One problem, of course, is coming up with a useful definition of
> the std::object class.
>
> namespace std
> {
> class object
> {
> // Does not have any data members
> public:
> virtual ~object();
> object();
> object(const object &r);
>
> // What other functions?
>
> // Perhaps...
> string toString() const;
> long int hash() const;
> typeid_t * typeinfo() const;
> };
> }
>
> Without any useful member functions, all that this buys us is the
> ability to pass objects around as arbitrary 'object' types instead
> of 'void*' types:
>
> #include <object> // Declares class std::object
>
> void foo(std::object *p)
> {
> bar(p);
>
> KnownType * kt = static_cast<KnownType *>(p);
> baz(kt);
> }
I cant see a difference between an object pointer or a void pointer
unless class object contains some data. ANY C++ object would grow
for the size of these members. May be ok for JAVA, but I dont
want to pay for what I dont use; I wouldnt use class object.
volker
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1999/07/28 Raw View
Biju Thomas <b_thomas@ibm.net> writes:
>David R Tribble wrote:
>>
>> I was recently thinking about how Java and other O-O languages
>> define all class types to inherit class 'Object' implicitly. In the
>> case of Java, this provides some useful capabilities, such as the
>> fact that all objects have an overridable 'toString()' member function,
>> and any type can be passed to a function as an argument of type
>> 'Object' (which seems a bit cleaner than 'void*').
>>
>[...]
>> Comments?
>
>How will it handle cases of multiple inheritance without the overhead of
>virtual inheritance? Java (and Smalltalk?) doesn't face that problem.
Well, there's no non-const data members being inherited, only virtual
functions, and the final definitions of the virtual functions will always
be in the most derived class. So the compiler could do static checking
as if it were virtual inheritance (i.e. conversion to `object *' would
not be treated as ambiguous) but do code generation as if it were
ordinary inheritance.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/28 Raw View
> David R Tribble wrote:
>>
>> I was recently thinking about how Java and other O-O languages
>> define all class types to inherit class 'Object' implicitly. In the
>> case of Java, this provides some useful capabilities, such as the
>> fact that all objects have an overridable 'toString()' member
>> function, and any type can be passed to a function as an argument
>> of type 'Object' (which seems a bit cleaner than 'void*').
Biju Thomas wrote:
> How will it handle cases of multiple inheritance without the overhead
> of virtual inheritance? Java (and Smalltalk?) doesn't face that
> problem.
blargg wrote:
> What happens here?
>
> struct A {
> virtual ~A();
> };
>
> struct B {
> virtual ~B();
> };
>
> struct C : A, B { };
>
> Do the types implicitly derived virtually from std::object? Nice
> overhead there.
Eiffel has an implicitly inherited 'Object' class, and it supports
multiple inheritance. (I think Smalltalk does, too.) Obviously,
at least one language has solved the overhead problem. (Of course,
Eiffel employs a smarter backend and linker than C++.)
-- David R. Tribble, david@tribble.com --
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/28 Raw View
Volker Denneberg wrote:
>
> David R Tribble wrote:
> > One problem, of course, is coming up with a useful definition of
> > the std::object class.
> >
> > namespace std
> > {
> > class object
> > {
> > // Does not have any data members
> > public:
> > virtual ~object();
> > object();
> > object(const object &r);
> >
> > // What other functions?
> >
> > // Perhaps...
> > string toString() const;
> > long int hash() const;
> > typeid_t * typeinfo() const;
> > };
> > }
> >
> > Without any useful member functions, all that this buys us is the
> > ability to pass objects around as arbitrary 'object' types instead
> > of 'void*' types:
> >
> > #include <object> // Declares class std::object
> >
> > void foo(std::object *p)
> > {
> > bar(p);
> >
> > KnownType * kt = static_cast<KnownType *>(p);
> > baz(kt);
> > }
>
> I cant see a difference between an object pointer or a void pointer
> unless class object contains some data. ANY C++ object would grow
> for the size of these members. May be ok for JAVA, but I dont
> want to pay for what I dont use; I wouldnt use class object.
This is the first good argument I've seen against std::object.
The only overhead I see, though, is that the data pointed to by
all of the _vtbls in all of the non-POD classes in a program would
would have to be larger to include pointers to all of the extra
virtual member functions added by std::object. This might be a
noticeable space increase for programs with hundreds of classes.
-- David R. Tribble, david@tribble.com --
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/28 Raw View
David R Tribble <david@tribble.com> wrote:
>> would it be useful if C++ did this, i.e., if all [non-POD] class
>> types inherited class std::object implicitly?
Siemel Naran wrote:
> I don't think this would be a good idea as it lowers type safety.
> Consider: In current C++ we can have a hierarchy of Animals -- eg,
> Goat Sheep Lion all derived from the most base class Animal. And
> we can have a hierarchy of Shapes -- eg, Rectangle Circle Ellipse
> all derived from the most base class Shape. Lots of other
> examples. And the type Animal* (which is basically an Animal
> object) is distinct from the type Shape* (which is basically a
> Shape object). But making a common base class std::object would
> make all objects (or all polymorphic objects) essentially
> equivalent. This is a blow to strong type safety.
Is this your argument against this practice as found in languages
like Java, Eiffel, and Smalltalk? Sorry, but I don't follow your
reasoning about how a common root class type breaks strong type
safety. (Deep down, all object are equivalent ;-) Could you
provide a concrete example? Please convince me that std::object*
is worse than void*.
-- David R. Tribble, david@tribble.com --
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Joe Gottman <joegottman@worldnet.att.net>
Date: 1999/07/29 Raw View
Volker Denneberg wrote:
> David R Tribble wrote:
> >
> > I was recently thinking about how Java and other O-O languages
> > define all class types to inherit class 'Object' implicitly. In the
> > case of Java, this provides some useful capabilities, such as the
> > fact that all objects have an overridable 'toString()' member function,
> > and any type can be passed to a function as an argument of type
> > 'Object' (which seems a bit cleaner than 'void*').
> >
> > So my question is, would it be useful if C++ did this, i.e., if all
> > class types [*] inherited class std::object implicitly?
> >
> > [*] To eliminate the overhead for POD types, we would restrict the
> > implicit inheritance to only classes having one or more virtual
> > member functions (i.e., types having a _vtbl). (Languages like Java
> > don't have POD class types because all member functions are implicitly
> > virtual, meaning that all objects have a hidden _vtbl-like element;
> > this explains why all Java classes can inherit class 'Object'
> > cheaply.)
> >
> > One problem, of course, is coming up with a useful definition of
> > the std::object class.
> >
> > namespace std
> > {
> > class object
> > {
> > // Does not have any data members
> > public:
> > virtual ~object();
> > object();
> > object(const object &r);
> >
> > // What other functions?
> >
> > // Perhaps...
> > string toString() const;
> > long int hash() const;
> > typeid_t * typeinfo() const;
> > };
> > }
> >
> > Without any useful member functions, all that this buys us is the
> > ability to pass objects around as arbitrary 'object' types instead
> > of 'void*' types:
> >
> > #include <object> // Declares class std::object
> >
> > void foo(std::object *p)
> > {
> > bar(p);
> >
> > KnownType * kt = static_cast<KnownType *>(p);
> > baz(kt);
> > }
>
> I cant see a difference between an object pointer or a void pointer
> unless class object contains some data. ANY C++ object would grow
> for the size of these members. May be ok for JAVA, but I dont
> want to pay for what I dont use; I wouldnt use class object.
>
>
Also, remember that C++ allows multiple inheritance and Java doesn't. A
major headache with multiple inheritance is the "deadly diamond" class
structure:
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
(See Scott Meyer's _More Effective C++_ to see exactly why it is a
headache).
If everything inherited from Object, then every instance of multiple
inheritance would have the above structure.
--
Joe Gottman
joegottman@worldnet.att.net
The philosophy of C++: "Nothing is false; everything else is true."
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/07/29 Raw View
In article <379F775A.CE052EBD@tribble.com>, David R Tribble
<david@tribble.com> writes
>The only overhead I see, though, is that the data pointed to by
>all of the _vtbls in all of the non-POD classes in a program would
>would have to be larger to include pointers to all of the extra
>virtual member functions added by std::object. This might be a
>noticeable space increase for programs with hundreds of classes.
No, worse than that, all udt's would have to have vtbls and all objects
would have to include a pointer to the relevant vtbl.
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/29 Raw View
Francis Glassborow wrote:
>
> David R Tribble <david@tribble.com> writes
> >The only overhead I see, though, is that the data pointed to by
> >all of the _vtbls in all of the non-POD classes in a program would
> >would have to be larger to include pointers to all of the extra
> >virtual member functions added by std::object. This might be a
> >noticeable space increase for programs with hundreds of classes.
>
> No, worse than that, all udt's would have to have vtbls and all
> objects would have to include a pointer to the relevant vtbl.
No, as I mentioned in my first post, I would limit the implicit
inheritance of std::object to only classes having vitual member
functions, i.e., only UDTs already having a _vtbl. I would
specifically exclude POD types from implicitly inheriting
std::object. That way there is no extra overhead added to objects
beyond what they already have today.
-- David R. Tribble, david@tribble.com --
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 1999/07/29 Raw View
Joe Gottman wrote:
>
> Volker Denneberg wrote:
>
> > David R Tribble wrote:
> > >
> > > I was recently thinking about how Java and other O-O languages
> > > define all class types to inherit class 'Object' implicitly.
...
> >
> > I cant see a difference between an object pointer or a void pointer
> > unless class object contains some data. ANY C++ object would grow
> > for the size of these members. May be ok for JAVA, but I dont
> > want to pay for what I dont use; I wouldnt use class object.
> >
> >
>
> Also, remember that C++ allows multiple inheritance and Java doesn't.
> A major headache with multiple inheritance is the "deadly diamond"
> class structure:
> class A {};
> class B : public A {};
> class C : public A {};
> class D : public B, public C {};
>
> (See Scott Meyer's _More Effective C++_ to see exactly why it is a
> headache).
> If everything inherited from Object, then every instance of
> multiple inheritance would have the above structure.
Of course, we could allow the compiler to handle the inheritance of
class std::object in special ways, since it would be known to the
compiler as a special class anyway.
-- David R. Tribble, david@tribble.com --
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]