Topic: new syntax for new operator


Author: akv@cacs.usl.edu (Anil Vijendran)
Date: 1995/12/04
Raw View
>>>>> On 30 Nov 1995 17:09:36 GMT, dak <pierreba@poster.cae.ca> said:

    dak> B. Usage
    dak> --------

    dak> Usage of the new operators are multiples. The first is the possibility to
    dak> distinguish between stack-allocated, static-heap and dynamic-heap

Actually instead of adding to new, I'd be inclined to say we need
different ``constructor classes'' (maybe even ``destructor
classes''). That is, static constructors, automatic constructors and
dynamic constructors. One could even try cooking up a reasonable
subsumption relationship between the three to avoid breaking existing
code.

For example,

 class A {
 public:
  static A(int); // will be called for objects of A that
                        // reside on .data (data segment)
  automatic A(int); // will be called for objects of A that
                           // reside on stack segment
  dynamic A(int); // will be called for objects of A that
                         // are allocated using new.

 };

(Oops that should be "auto" instead of "automatic"... never used it.)

Combine this with `explicit' and it becomes `funny' :-)


    dak> variables.  Many programs need that capability, notably when related to
    dak> smart pointers and garbage collection. Another usage (the one which
    dak> prompted me to write this) would be in the context of OODBMS. The
    dak> ability to communicate with the server and take different actions depending
    dak> on the location of the variable can dramatically improve the performance
    dak> of some operations.

I believe that the (sort of) general case is one of letting an object
grab certain interesting things that were passed to new and stay
knowledgeable about them.

This would be possible if there were some "function signature prefix
matching" between all the arguments that were passed to new and a
constructor of that class whose first few arguments matched it:

 class A {
        public:
           A(int) { .. } // ordinary constructor
           A(Allocator* al, int) { .. } // allocated on some heap
        // ..
        };

Now,

 A a(5);

        // object `a' would know that it was allocated either on the
        // stack or .data or it was allocated using plain new.


 class FancyHeap : public Allocator { ... };

 FancyHeap* heap = new FancyHeap(..);

 A* pa = new (heap) A(5); // this calls A::A(Allocator*, int)

 class ForeignHeap { ... };

 ForeignHeap* heap = new ForeignHeap(..);

 A* pa = new (heap) A(5); // error: heap does not match any
                                 // prefix argument in the constructor

The last example shows that a class can control what kind of heaps its
objects can be allocated in.

Since that would break code and as a matter of fact, force root
classes (atleast for allocators and such), one could say, if there is
a match in the arguments passed to new and the first few arguments of
a constructor, then that would be called else the effect would be as
it is now. That would make the last example call the A::A(int)
constructor, without flagging a compile-time error.

What happens if the new arguments match the constructor and there is a
mismatch in the actual constructor arguments? Ah... there's the
hornet's nest.

I'm not trying to say this SHOULD be in the language or anything. But
I don't see why it shouldn't be :-) (The basic question: how would all
these things be possible without an extension?)

--
Peace.... +<:-)

Anil


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: claus@faerber.muc.de (Claus Andre Faerber)
Date: 1995/12/04
Raw View
pierreba@poster.cae.ca (30 Nov 95):

>[...]
> -- Start example --
>
> class A
> {
>  public:
>   // default new for static variables.
>   static void operator new ( void *, size_t );
>   // overloaded new for static variables.
>   static void operator new ( void *, size_t, int a, int b );
>   // delete for static variables.
>   static void operator delete ( void *, size_t );
>
>   // default new for auto variables.
>   auto void operator new ( void *, size_t );
>   // overloaded new for auto variables.
>   auto void operat+7      " >/w  2  c+e_t, int a, int b );
>   // delete for auto variables.
>   auto void operator delete ( void *, size_t );
> };
>
> static A a2;                 // static A object using declared default new.
> static A a2 = new (88,91) A; // static A object using overloaded new.
>
> int main (void)
> {
>  A a3;                 // auto A object with declared default new.
>  A a4 = new (88,91) A; // auto A object with overloaded new.

This sytax is inconsistent with the existing one: new always return a
poiter to the object created.

>  ...
>
> } // at this point the declared delete operator is called for each A
>
> -- End example --

Another point is, that you don't need a new operator for static and auto
objects, as they have reserved space in the data segment ("static-heap")
or on the stack, which is allocated at compile time.

Therefore you can't create static or auto objects with sizes calculated at
run time, either.

>[...]
> Usage of the new operators are multiples. The first is the possibility to
> distinguish between stack-allocated, static-heap and dynamic-heap
> variables.  Many programs need that capability, notably when related to
> smart pointers and garbage collection. Another usage (the one which
> prompted me to write this) would be in the context of OODBMS. The
> ability to communicate with the server and take different actions depending
> on the location of the variable can dramatically improve the performance
> of some operations.

I suggest defining a new syntax for *constructors* (or any member
functions) instead:

class A
{
        A ( );           // Perhaps we should create a new keyword like
        A ( int abc );   // "dynamic" for heap objects.

        A ( ) static;
        A ( int abc ) static;

        A ( ) auto;
        A ( int abc ) auto;

        DoSomething ( int* xyz );
        DoSomething ( int* xyz ) static;
        DoSomething ( int* xyz ) auto;

        ~A( );
        ~A( ) static;
        ~A( ) auto;
};

This also meets the syntax used by many compiler vendors to differentiate
far and near methodes.

>[...]


===================================================
Claus Andre Faerber          <claus@faerber.muc.de>
===================================================


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: dak <pierreba@poster.cae.ca>
Date: 1995/12/07
Raw View
I wrote in a previous message:
>
> -- Start example --
>
> class A
> {

[snip...]

> static A a2;                 // static A object using declared default new.
> static A a2 = new (88,91) A; // static A object using overloaded new.
>
> int main (void)
> {
>  A a3;                 // auto A object with declared default new.
>  A a4 = new (88,91) A; // auto A object with overloaded new.
>

[snip...]

> As can be seen, the syntax does not break any existing code since it is
> currently illegal to assign the result of a new operation to the declared
> variable when the pointer types are not compatible (point 1).

Someone pointed out that the syntax could be confused if a constructor takes
a pointer to its own class as argument.  I had originally a different syntax
but changed it just before posting thinking the new one was more consistent.
Duh! Never change a post without thinking...  The original syntax had the
keywords in the calls:

static A a2 = static new (88,91) A;
...
A a4 = auto new (88, 91) A;

Now I believe it is a whole new syntax without possible confusion...



---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: dak <pierreba@poster.cae.ca>
Date: 1995/11/30
Raw View
I would like to propose a new extension to the new and delete operator: the
possibility of having overloaded versions for stack and static variables.
I believe my proposition meets the usual requirements for a proposed change
(except that it is quite too late for it to be accepted...):

1. It doesn't break any existing code.
2. It can have a clear syntax which doesn't conflict with existing ones.
3. It doesn't add any penalty to programs not using it.
4. It extends the language in a logical way.
5. It adds orthogonality and completness.
6. It's simple.
7. It adds capabilities not available in any other way

I intend to prove each point above while explaining the details of my
proposition.  It will be presented in the following order:

A. Syntax and Example
B. Usage
C. Conclusion


A. Syntax and Example
---------------------

The syntax would simply extend the (already overused) "static" keyword and
the totally unused "auto" keyword.  The following excerpt shows how the new
operators would be declared in a class and used in a program. Note that the
new operators receive the pointer to the memory region since they do not need
to allocate it themselves.

-- Start example --

class A
{
 public:
  // default new for static variables.
  static void operator new ( void *, size_t );
  // overloaded new for static variables.
  static void operator new ( void *, size_t, int a, int b );
  // delete for static variables.
  static void operator delete ( void *, size_t );

  // default new for auto variables.
  auto void operator new ( void *, size_t );
  // overloaded new for auto variables.
  auto void operator new ( void *, size_t, int a, int b );
  // delete for auto variables.
  auto void operator delete ( void *, size_t );
};

static A a2;                 // static A object using declared default new.
static A a2 = new (88,91) A; // static A object using overloaded new.

int main (void)
{
 A a3;                 // auto A object with declared default new.
 A a4 = new (88,91) A; // auto A object with overloaded new.

 ...

} // at this point the declared delete operator is called for each A

-- End example --

As can be seen, the syntax does not break any existing code since it is
currently illegal to assign the result of a new operation to the declared
variable when the pointer types are not compatible (point 1). The syntax
is clear both in the declaration in the class and the usage in the
program (point 2).

Also, a class which does not declare a static nor an auto new operator does
not suffer any performance penalty since the default behavior when none are
declared is to do nothing (point 3).

The new syntax is logical with previous uses of the keywords and completes
the new operator for variables which are not dynamically allocated (points
4 and 5). It is simple to use and to understand (point 6).

Furthermore, the current C++ language has no provision for detecting if
a variable was declared on the stack, on the static heap or allocated
dynamically. With this extension, it is possible to track or add flags
a variable indicating this in an extensible and safe way (point 7).


B. Usage
--------

Usage of the new operators are multiples. The first is the possibility to
distinguish between stack-allocated, static-heap and dynamic-heap
variables.  Many programs need that capability, notably when related to
smart pointers and garbage collection. Another usage (the one which
prompted me to write this) would be in the context of OODBMS. The
ability to communicate with the server and take different actions depending
on the location of the variable can dramatically improve the performance
of some operations.


C. Conclusion
-------------

Like I stated at the beginning, I believe this proposition meets all
requirements but one: it's just too late to add it to the current language
without further delaying the publication of the standard.  On the other
hand, the proposition is clear, simple, and easy to implement.

While I don't expect the Standard Commitee to even examine this
proposition, I would be satisfied if it became a de facto extension
supported by most compiler vendors (I can wish).


[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]






Author: martelli@cadlab.it (Alex Martelli)
Date: 1995/12/01
Raw View
dak <pierreba@poster.cae.ca> writes:
 ...
> A a4 = new (88,91) A; // auto A object with overloaded new.
 ...
>As can be seen, the syntax does not break any existing code since it is
>currently illegal to assign the result of a new operation to the declared
>variable when the pointer types are not compatible (point 1). The syntax

This is not necessarily true.  If class A has a constructor accepting
an A* argument, or some other related cases (e.g., A publically derives
from B and has a constructor accepting a B* argument), and operator new
has an overloaded version (global or class-specific) accepting two extra
int arguments, then the expression you propose is not currently illegal.
It is not immediately clear whether the resulting ambiguity can be solved
in a totally satisfactory way.

Note that an A constructor taking a B* argument, with A publically
derived from B, is quite idiomatical in envelope/letter, aka 'handle',
idioms, a la:

class Foo_abstract {
public: virtual void Bar() const = 0;
        static Foo_abstract * DefaultFooFactory();
        // etc
};

class Foo_envelope: public Foo_abstract {
    Foo_abstract *letter;
public:
    Foo_envelope(Foo_abstract *p=0): letter(p) {
       if(!letter) letter=DefaultFooFactory();
    }
    virtual void Bar() const { letter->Bar(); }
    // etc
};


Alex
--
DISCLAIMER: these are MY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: martelli@cadlab.it -- Phone: +39 (51) 597 313  [Fax: 597 120]
Cad.Lab S.p.A., v. Ronzani 7/29, 40033 Casalecchio (BO), Italia


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]