From -7231783828397250355
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,6d43dabd81d37c8e
X-Google-Attributes: gidf78e5,public
X-Google-ArrivalTime: 2003-01-25 13:02:01 PST
Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!kibo.news.demon.net!mutlu.news.demon.net!demon!mail2news.demon.co.uk!devnull
From: danielgutson@hotmail.com (danielgutson@hotmail.com)
Newsgroups: comp.std.c++
Subject: Re: suggestions: about constructors and destructors
Date: Sat, 25 Jan 2003 21:01:55 +0000 (UTC)
Organization: http://groups.google.com/
Lines: 243
Approved: fjh@cs.mu.oz.au (Fergus Henderson , moderator of comp.std.c++)
Message-ID: <23478c42.0301242256.a3709a4@posting.google.com>
References: <23478c42.0301230926.39a6959c@posting.google.com>
 <7f2735a5.0301241511.20024ed6@posting.google.com>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: mail2news.demon.co.uk 1043528515 12880 10.0.0.1 (25 Jan 2003 21:01:55 GMT)
X-Complaints-To: abuse@demon.net
NNTP-Posting-Date: Sat, 25 Jan 2003 21:01:55 +0000 (UTC)
X-Received: from mulga.cs.mu.oz.au ([128.250.1.22])
	by news.demon.co.uk with esmtp (Exim 4.05)
	id 18cXR2-0003Lb-00
	for mail2news@news.news.demon.net; Sat, 25 Jan 2003 21:01:53 +0000
X-Received: from localhost (localhost [[UNIX: localhost]]) by mulga.cs.mu.OZ.AU
	id IAA19948; Sun, 26 Jan 2003 08:01:49 +1100 (EST)
X-Authentication-Warning: mulga.cs.mu.OZ.AU: fjh set sender to devnull@stump.algebra.com using -f
X-Path: comp-std-cpp-robomod!not-for-mail
X-Robomod: STUMP, ichudov@algebra.com (Igor Chudov)
X-Delivered-to: std-c++@ncar.ucar.edu
X-NNTP-Posting-Date: 25 Jan 2003 06:56:36 GMT
X-Spam-Status: No,
 hits=-8.4 required=5.0	tests=FORGED_HOTMAIL_RCVD,NOSPAM_INC,QUOTED_EMAIL_TEXT,
	REFERENCES,SPAM_PHRASE_03_05	version=2.41
X-Newsgroups: comp.std.c++
Xref: archiver1.google.com comp.std.c++:17520

allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0301241511.20024ed6@posting.google.com>...
> danielgutson@hotmail.com (danielgutson@hotmail.com) wrote
> > Newgroupers:
> 
> ??

's' missing. I don't have an English++ compiler here :)

Before starting my comments, a very good friend told me about the lack
of 'motivation' in my proposals descriptions. And it is absolutely
trueth.
Sorry about this, I did not expected you are sorcerers for guessing
why I'm proposing these. From now on, I'll include purposes, reasons
and motivations in my postings.

> 
> In your example, it looks like you aren't actually using the int.

Too light example. I agree. I often use 'destroy' function (with
delete this) for reference counting. And I hope that my lines in this
message will differentiate the concept.

> You just want the destructor to have a different "signature",
> so that you can't destroy the "Contained" object normally.

50% and 50%: first, I do want to make hiding available also for
destructors (there comes your observation about signature); second, I
want to make clear that my class 'needs' such parameter/s for
destruction, and that this is the only way to destroing it (I'm
writing in 'example' mode).

Let me think an example (not too good for this). Suppose there is a
'handleManager', a class that gives you a handle to something, and
once you finish your usage, you 'return' it.

class HandlesManager
{ public: 
    Handle getHandle();
    void endOfUse(Handle h);
  ...
};

and that a class uses such handles, and you don't want to keep a
reference to the HandlesManager nor make it a singleton (for any
architectural reason).
So, you pass the manager to its constructor, and to the destructor:

class AUser
{
public:
   AUser(HandlesManager& mgr)
     :_h ( mgr.getHandle() ) {}

   ~AUser(HandlesManager& mgr)
   { mgr.endOfUse( _h );    }

private:
  const Handle _h;
};

Consecuences:
   1) readability: the idea is self-documented, needs it for all the
life of the instance of AUser, gets it at the beginning, ends it at
the end.
   2) I think this is more natural that making private the destructor
and providing a function 'destroy'-like: we are using the native
concept of the destructor! Why should we redefine the wheel if the
extension is natural? Constructor ANALOGOUS Destructor. Constructor
ACCEPTS parameters, but Destructor NOT(ACCEPTS) parameters, then the
analogy is incomplete.
  3) you can have different [overloaded] destructors (accepting
different parameters).

Suppose you have a default constructor, and a non-default destructor.
Then it's ok for me that this is not valid:

void f()
{
   AUser a;

} // error: no default destructor available

But, a rule (I agree this could be questionable) could be that if the
called constructor has the same signature that the destructor, then
the same parameters shoud be used: [considering the original AUser]

void f(HandlesManager& mgr)
{
   AUser a(mgr);

} // a.~AUser(mgr) is invoked here

>     void foo() {
>         Contained c; // Would be illegal, 'cause you can't destroy it.
>         Contained *d = new Contained; // Legal
>         delete d;                     // Not legal ("default destructor")
>         delete(1) d;                  // Legal
>     }
> Is this what you had in mind?

Just a warn: I want to differentiate a non-default destructor against
overloading the delete operator. (In the same sense we differentiate
new overloading from constructor overloading).

> 
> Conventional wisdom is: An object ought to know it's own state. Once
> you destroy it, there is no more state. Therefore, there's no reason
> to pass arguments to the destructor.

Indeed, the destruction is a process itself when you still have the
object.
And providing parameters to its [last] process seems natural to me, as
far as it's just another process. For example, you can provide hints
about 'how to destruct' the object.
The destruction is requested by the client, and the client might want
to provide such information.
Another complain of the 'destroy' operation, is that you must
duplicate an already existent [native] mechanism, you must perform
your 'proprietary' destruction, for example when you have a virtual
destructor, you must also make your 'destroy' virtual.

This is my general position: I hate to make parallel things that the
language does just because it is not general enough. If it already
provides the concept, but is not general, let's generalize it instead
of making [THE SAME]+[extension].

> Same, except you'd use p.destroy(1) at the end instead of delete p(1).
> Besides -- what happens if S defines operator()? Your statement above
> would call operator(), and delete whatever it returns...

Absolutely correct. I forgot about this. Help me finding an
alternative syntax :)   (in few days I'll post it if you don't want;
but I invite you to mail to my personal email address if you want, and
please consider this as a friendly act)

> >      struct C
> >      {
> >         const C() { ... };
> >         C() { ... };
> >      };
> 
> If this WAS legal C++, the const keyword ought to come after.

NO: I already thought about this.

C() const  denotes that you cannot change the content of this in the
process.
But during construction, you ARE changing and assigning things. The
class becomes const immediately after your construction process ends.
Same thing for destructor.
In the example I gave you lines above about the HandlesManager, this
still holds: we can write

class AUser
{
public:
   const AUser(HandlesManager& mgr) { ... }
   const ~AUser( same thing ...
};

The only thing you change within this class is the assignment of the
 const Handle _h
attribute, that takes place during the construction.

Providing *only* a const constructor, hides the default constructor,
and forces the 'read only' usage of the class.
I think that passive classes are a good example for this.

Another (esthetical) reason of placing the 'const' at the left, is
that looks equal to the declaration:
  const AUser a;        // instance decl.

looks like

{
  const AUser( ... );   //constructor decl.


> Still don't understand the motivation for this.

I hope I was clearer this time. I consider your no-understanding as my
fault (please, I expect I don't sound ironic)

> >    void g(void)
> >    {
> >       A a[10](constr_index<0>);
> >       A b[10][20](constr_index<0>+constr_index<1>);
> >    }

> 
> And this I don't get at all. Seems like an elaborate mechanism that would

sorry, let me clarify:

I mean by the 'constr_index<n>' keyword, that the compiler will pass
the i-th position (the index) in that parameter while invoking the
constructor, where 'n' is the n-th dimension.

> only be appropriate when the constructor takes a single int parameter.
> I'd rather see operator new[] accept a functor.

No, I don't want to mess with the operator new. I associate it to the
memory allocation specific instead of the construction process once
you get the memory allocated.

> Even then, it would only work when the Customer object has a single
> parameter -- rather special-purpose, I should think. And does it

that's the 'n' parameter in 'constr_index<n>'.

If you want an object member of an array, accepting the index in a
parameter and another value in other:

class Element
{ public:
  Element( size_t index, float otherThing);
};

then:

  Element e[10]( constr_index<0>, 3.1415 );

The compiler just passes the 'index number' of the first (and unique)
dimension of this in the first parameter.
<0> means the first dimension. If you have a 2x2 matrix, you will be
able to use
     constr_index<0> and constr_index<1> 

> solve a problem that std::vector<> can't also solve?

I didn't understand. I think it will be clear with the above
explanation; otherwise, please let me know.

 Daniel.

pd: thanks for your feedback, very good.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]



