Is it legal to directly call a constructor?

G

goodbyeera

class A {
void f() { this->A::A(); }
};

Let's just put away the logic of the program for a moment. I'm just
wondering whether this syntax is legal in standard C++ or not. This
compiles OK in VC and GCC, but fails in Comeau. I'm not able to find
a direct answer to this in the standard. Can anyone help to explain
whether it is syntactically legal? Thank you very much.
 
A

Alf P. Steinbach

* (e-mail address removed):
class A {
void f() { this->A::A(); }
};

Let's just put away the logic of the program for a moment. I'm just
wondering whether this syntax is legal in standard C++ or not.

The above is not valid syntax in standard C++.

But regarding your question which you inconveniently put only in the subject
line, "Is it legal to directly call a constructor", yes of course it is
(regarding a constructor of a most derived class the only indirect way is via
the 'new' operator), and that's what you do every time you call a constructor.

Given your example, what you probably meant was to ask, "Does C++ support
calling a constructor on existing storage?", and the answer to that is also yes.

This
compiles OK in VC and GCC, but fails in Comeau.

It shouldn't compile with any compiler.

For g++, have you remembered to specify -pedantic and -std=c++98?

For VC, which version?

I'm not able to find
a direct answer to this in the standard. Can anyone help to explain
whether it is syntactically legal? Thank you very much.

The C++ syntax for calling a constructor on existing storage is the basic
placement new, like, for emulating what you're trying to do above,

#include <new>

...

this->A::~A(); // Must first be destroyed.
::new( this ) A(); // Resurrect.

This is extremely dangerous when you don't know what you're doing, which you
don't when you're enquiring about the syntax. It's even extremely dangerous when
you do think you know what you're doing, or perhaps especially then! There's
very seldom any reason to do it; if or when you feel that that the above could
be a solution to something, ask about solutions to the something (they will
exist, and they will not include the above).


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Alf P. Steinbach:
* (e-mail address removed):

The above is not valid syntax in standard C++.

But regarding your question which you inconveniently put only in the
subject line, "Is it legal to directly call a constructor", yes of
course it is (regarding a constructor of a most derived class the only
indirect way is via the 'new' operator

Or by having an instance of that class as a default-constructed member.

Sorry.

Didn't think of that when just typing away...


), and that's what you do every
 
G

goodbyeera

Thank you very much for your reply.
It shouldn't compile with any compiler.

For g++, have you remembered to specify -pedantic and -std=c++98?
I have to apologize that the code in the original post doesn't compile
in g++. It's my mistake. However, the following code compiles in g++
and vc.
class A {};
int main()
{
A::A();
}
Is this syntactically legal in standard C++? I only know that "A()"
is the syntax used to create a temporary object of A.
And even more, the following code compiles in g++ (but not in vc).
#include <typeinfo>
class A {};
int main()
{
typeid(A::A);
}
What does this mean?
PS: By saying g++, actually I'm using mingw through dev-c++ on
windows.
For VC, which version?
The code in the original post compiles in VC2008SP1.
 
A

Alf P. Steinbach

* (e-mail address removed):
Thank you very much for your reply.

I have to apologize that the code in the original post doesn't compile
in g++. It's my mistake. However, the following code compiles in g++
and vc.
class A {};
int main()
{
A::A();
}
Is this syntactically legal in standard C++?

Yes, AFAIK (regarding the qualification with A::, but check the standard if it
matters). It constructs a temporary of type A.

I only know that "A()"
is the syntax used to create a temporary object of A.
Yes.


And even more, the following code compiles in g++ (but not in vc).
#include <typeinfo>
class A {};
int main()
{
typeid(A::A);
}
What does this mean?

typeid is a built-in operator.

C++ allows any expression that produces a value, void, or a reference, to be
used as a statement; this includes writing e.g.

42;

You should up the compiler's warning level to get some diagnostic.

Check your documentation (textbook, C++ standard, whatever) regarding typeid.

PS: By saying g++, actually I'm using mingw through dev-c++ on
windows.
The code in the original post compiles in VC2008SP1.

It really shouldn't.

But have you checked the compiler's documentation about non-conformance issues?

It might be (and probably is) a VC-specific language extension, for backwards
compatibility with pre-standard code.


Cheers & hth.,

- Alf
 
V

Victor Bazarov

Thank you very much for your reply.

I have to apologize that the code in the original post doesn't compile
in g++. It's my mistake. However, the following code compiles in g++
and vc.
class A {};
int main()
{
A::A();
}
Is this syntactically legal in standard C++? I only know that "A()"
is the syntax used to create a temporary object of A.
And even more, the following code compiles in g++ (but not in vc).
#include <typeinfo>
class A {};
int main()
{
typeid(A::A);
}
What does this mean?
PS: By saying g++, actually I'm using mingw through dev-c++ on
windows.
The code in the original post compiles in VC2008SP1.

I think that 'A::A' is the same as 'A' outside of 'A', so when you write

A::A();

it's the same as to write

A();

if you're not inside the 'A' class itself (not inside of one of its
member functions). Try writing

A::A::A::A::A::A::A::A::A();

and see what happens. :)

V
 
G

goodbyeera

class A {};
Yes, AFAIK (regarding the qualification with A::, but check the standard if it
matters). It constructs a temporary of type A.
I can't find a direct answer from the standard whether this syntax is
legal or not. And FYI, Comeau doesn't compile this code.
typeid is a built-in operator.
typeid should take an expression or a type as its operand, but I don't
know what kind of expression or type A::A represents.
 
V

Victor Bazarov

I can't find a direct answer from the standard whether this syntax is
legal or not. And FYI, Comeau doesn't compile this code.

typeid should take an expression or a type as its operand, but I don't
know what kind of expression or type A::A represents.

Every class has a name of itself injected into its scope. So, 'A::'
resolves to the scope of the class A, and the name 'A' in that scope
refers to the class itself, recursively. 'A::A::A::A::A::A ...' is the
same as 'A', but only outside of the class itself, IIRC.

V
 
G

goodbyeera

I think that 'A::A' is the same as 'A' outside of 'A', so when you write
    A::A();
it's the same as to write
    A();
if you're not inside the 'A' class itself (not inside of one of its
member functions).  Try writing
    A::A::A::A::A::A::A::A::A();
and see what happens. :)
I see what you mean. Is this compliant with C++ standard? Coz
neither VC nor Comeau compiles this code.
 
V

Victor Bazarov

I see what you mean. Is this compliant with C++ standard? Coz
neither VC nor Comeau compiles this code.

Maybe I got it backwards and it's only allowed inside the class scope...

V
 
G

goodbyeera

Maybe I got it backwards and it's only allowed inside the class scope...
In g++, it's allowed inside both inside and outside class scope. In
VC and Comeau, it's not allowed in either scope.
 
A

Alf P. Steinbach

* blargg:
You can't directly call a constructor in C++. The closest you can do is
use placement new to construct an object in a buffer you provide:

On the contrary, that's the farthest from a direct constructor call. The
placement new has to work very indirectly because it has to set up an exception
handler, plus in the general case it has to call the class' allocation function,
before invoking the constructor with the specified arguments, which it has held
on to until now. In contrast, an ordinary direct constructor call is a direct
call, which you can readily verify by inspecting the machine code (unless you
have a really perverse C++ implementation).

Cheers & hth.,

- Alf
 
J

James Kanze

* (e-mail address removed):
The above is not valid syntax in standard C++.
But regarding your question which you inconveniently put only
in the subject line, "Is it legal to directly call a
constructor", yes of course it is (regarding a constructor of
a most derived class the only indirect way is via the 'new'
operator), and that's what you do every time you call a
constructor.

It really hinges on what you mean by "direct". There is no
syntax in C++ which "calls a constructor"; every *syntax* which
results in a constructor call also allocates memory. Formally,
at least---placement new can be used to make the memory
allocation a no-op, of course. (But using placement new isn't
really what I'd call "direct". On the other hand, naming a base
class in a initialization list sure looks like a direct call to
the constructor to me.)

Anyway, his example made it more or less clear: he wants to call
the constructor like you'd call any other member function.
Which doesn't work, of course. Logically, since to call any
other member function (including the destructor), you need an
object, and the only way to get an object is to call the
constructor.

[...]
The C++ syntax for calling a constructor on existing storage is the basic
placement new, like, for emulating what you're trying to do above,

#include <new>

...

this->A::~A(); // Must first be destroyed.

Technically, only if it has a non-trivial destructor. (Also,
this->A::~A() is probably not a good idea, since the qualified
id prevents virtual function resolution. Although just about
anywhere virtual function resolution would make a difference,
explicit destruction will probably cause other problems as
well.)
::new( this ) A(); // Resurrect.
This is extremely dangerous when you don't know what you're
doing, which you don't when you're enquiring about the syntax.
It's even extremely dangerous when you do think you know what
you're doing, or perhaps especially then! There's very seldom
any reason to do it; if or when you feel that that the above
could be a solution to something, ask about solutions to the
something (they will exist, and they will not include the
above).

Even if you know perfectly what you're doing, it's dangerous,
because the person who ends up maintaining your code may not
realize you're doing it, and make some modification which breaks
it (e.g. by adding something to A::A() which might throw).
 
J

James Kanze

I think that 'A::A' is the same as 'A' outside of 'A', so when
you write

it's the same as to write

Not always. Consider:

struct A { A() ; } ;

A() { /* ... */ } // illegal...
A::A() { /* ... */ } // defines the constructor.

I think that the standard is actually somewhat ambiguous here,
at least when the class name is immediately followed by an
opening parentheses. According to the standard, "Constructors
do not have names. A special declarator syntax using an optional
sequence of function-specifiers (7.1.2) followed by the
constructor¿s class name followed by a parameter list is used to
declare or define the constructor." (Of course, if I read this
literally, it means that the both of the declarations above are
legal to define the constructor.)
if you're not inside the 'A' class itself (not inside of one
of its member functions). Try writing

and see what happens. :)

Whether you're inside the class or not doesn't matter. The only
question is whether the final A (the one followed by the ()) is
an instance of the "special declarator syntax[...]used to
declare or define the constructor".
 
J

James Kanze

* blargg:
On the contrary, that's the farthest from a direct constructor
call. The placement new has to work very indirectly because it
has to set up an exception handler, plus in the general case
it has to call the class' allocation function, before invoking
the constructor with the specified arguments, which it has
held on to until now. In contrast, an ordinary direct
constructor call is a direct call, which you can readily
verify by inspecting the machine code (unless you have a
really perverse C++ implementation).

What's your definition of "direct" in this context? In other
words, what makes a constructor call a "direct constructor
call", as opposed to an indirect constructor call? (In one very
real sense, all constructor calls are direct. Since you can't
take the address of the constructor, there's no way to get a
pointer to it in order to call it indirectly. But I suppose
neither you nor the original poster meant "direct" in that way,
although it would seem to me the most obvious meaning.)
 
A

Alf P. Steinbach

* James Kanze:
It really hinges on what you mean by "direct".

Just the opposite of "indirect". :)

E.g. that could be debated for the case of a virtual call of an ordinary member
routine, is it direct or indirect? At the source code level it's direct. At the
machine code level it's indirect. Just flinging about the word "direct" would
not be sufficient for that case. One would need to be more specific.

But happily, for a constructor there's no such difference between the source
code level and the machine code level.

For a direct constructor call there are possible extra actions (memory
initializer list argument evaluation, invocations of base and member
constructors) but these actions are part of the called constructor. It's not
like there is some way to call the constructor without getting them, as you can
call a virtual routine non-virtually (machine code direct) or virtually (machine
code indirect). The direct -- implicit or explicit -- constructor call ends
up as a direct machine code call, plain and simple.

For an indirect call, operator new (placement or not!), there's indirection both
at the source code level and the machine code level. At the source code level
constructor arguments are handed to an operator, which will do the calling,
indirect. And at the machine code level some funny stuff is used to forward
those arguments after setting up exception handling (if a scheme is used where
that is necessary, i.e. not address look-up based handling) and after calling
the relevant allocation function, which forwarding constitutes an indirection.

There is no
syntax in C++ which "calls a constructor"; every *syntax* which
results in a constructor call also allocates memory. Formally,
at least---placement new can be used to make the memory
allocation a no-op, of course. (But using placement new isn't
really what I'd call "direct". On the other hand, naming a base
class in a initialization list sure looks like a direct call to
the constructor to me.)

Yes. It is a shame that the syntax of C++ differentiates many cases that really
should have been abstracted (e.g., no common "command" syntactic element, so
semicolons are present in a lot of places to /emulate/ that missing element!),
and fails to differentiate cases that really constitute distinct semantical
categories. I guess that this divide, the lack of a mostly one-to-one mapping
between syntax and semantics, leads to endless confusion for the newbies...

Anyway, his example made it more or less clear: he wants to call
the constructor like you'd call any other member function.
Which doesn't work, of course. Logically, since to call any
other member function (including the destructor), you need an
object, and the only way to get an object is to call the
constructor.

Uh, from a pedantic point of view, no. You don't need an object to call a static
member function. And, still pedantically, it depends on the meaning of the word
"call": for a source code level call that is only evaluated at compile time you
don't need an object; indeed there is no object at compile time. ;-)

[...]
The C++ syntax for calling a constructor on existing storage is the basic
placement new, like, for emulating what you're trying to do above,

#include <new>

...

this->A::~A(); // Must first be destroyed.

Technically, only if it has a non-trivial destructor. (Also,
this->A::~A() is probably not a good idea, since the qualified
id prevents virtual function resolution.

In this case qualified destructor call is IMHO the only reasonable idea, the
least ungood. For it's UB to resurrect the object as an object of different type
if it's accessed as the original type. And so one does, in practice, need to
know the exact most derived type, and that should be expressed in the code.

Although just about
anywhere virtual function resolution would make a difference,
explicit destruction will probably cause other problems as
well.)



Even if you know perfectly what you're doing, it's dangerous,
because the person who ends up maintaining your code may not
realize you're doing it, and make some modification which breaks
it (e.g. by adding something to A::A() which might throw).

Yeah. :)


Cheers,

- Alf
 
A

Alf P. Steinbach

* James Kanze:
What's your definition of "direct" in this context?

<quote origin="elsethread">
Just the opposite of "indirect". :)

E.g. that could be debated for the case of a virtual call of an ordinary member
routine, is it direct or indirect? At the source code level it's direct. At the
machine code level it's indirect. Just flinging about the word "direct" would
not be sufficient for that case. One would need to be more specific.

But happily, for a constructor there's no such difference between the source
code level and the machine code level.

For a direct constructor call there are possible extra actions (memory
initializer list argument evaluation, invocations of base and member
constructors) but these actions are part of the called constructor. It's not
like there is some way to call the constructor without getting them, as you can
call a virtual routine non-virtually (machine code direct) or virtually (machine
code indirect). The direct -- implicit or explicit -- constructor call ends
up as a direct machine code call, plain and simple.

For an indirect call, operator new (placement or not!), there's indirection both
at the source code level and the machine code level. At the source code level
constructor arguments are handed to an operator, which will do the calling,
indirect. And at the machine code level some funny stuff is used to forward
those arguments after setting up exception handling (if a scheme is used where
that is necessary, i.e. not address look-up based handling) and after calling
the relevant allocation function, which forwarding constitutes an indirection.
</quote>


Cheers,

- Alf
 
J

James Kanze

* James Kanze:
Just the opposite of "indirect". :)

Which is? :)

I raise the question because in C, when one spoke of an indirect
function call, it almost always meant a call through a pointer
to function. If we accept this definition, then there's no way
of calling a constructor indirectly (since you can't take its
address).
E.g. that could be debated for the case of a virtual call of
an ordinary member routine, is it direct or indirect?

Exactly. If I have an explicit pointer to function, which I
dereference, the call is indirect. If I call a global function
or a non-virtual member function directly, it's direct. But
what about a virtual function?
At the source code level it's direct. At the machine code
level it's indirect. Just flinging about the word "direct"
would not be sufficient for that case. One would need to be
more specific.
But happily, for a constructor there's no such difference
between the source code level and the machine code level.
For a direct constructor call there are possible extra actions
(memory initializer list argument evaluation, invocations of
base and member constructors) but these actions are part of
the called constructor. It's not like there is some way to
call the constructor without getting them, as you can call a
virtual routine non-virtually (machine code direct) or
virtually (machine code indirect). The direct -- implicit or
explicit -- constructor call ends up as a direct machine
code call, plain and simple.
For an indirect call, operator new (placement or not!),
there's indirection both at the source code level and the
machine code level.

Note that you've just changed the meaning of "direct". Even
when I use operator new, there's no "indirection" (through a
pointer) when calling the constructor, so in that sense, it is
direct. Syntactically, however, I've not written a "function
call expression" or a "constructor call expression" (which
doesn't exist in C++), so according to some definition, it is
indirect. It's still not as indirect as the call to g(),
however, when I call a function f(), in another translation
unit, which calls g(). The "new expression" is defined to do
two things (basically): call an allocator function, then call a
constructor. So it's direct in the sense that I've "directly"
(in the expression itself) requested that the constructor be
called.
At the source code level constructor arguments are handed to
an operator, which will do the calling, indirect.

I'm not sure I understand that. The "operator", here, is a
syntax construct. That construct does require that the compiler
generate a call to the constructor.
And at the machine code level some funny stuff is used to
forward those arguments after setting up exception handling
(if a scheme is used where that is necessary, i.e. not address
look-up based handling) and after calling the relevant
allocation function, which forwarding constitutes an
indirection.

There's no forwarding that I can see.
Yes. It is a shame that the syntax of C++ differentiates many
cases that really should have been abstracted (e.g., no common
"command" syntactic element, so semicolons are present in a
lot of places to /emulate/ that missing element!), and fails
to differentiate cases that really constitute distinct
semantical categories. I guess that this divide, the lack of a
mostly one-to-one mapping between syntax and semantics, leads
to endless confusion for the newbies...

Not just for the newbies:).
Uh, from a pedantic point of view, no. You don't need an
object to call a static member function.

Good point. Is a constructor a static member function? No,
since it has a this pointer. Is it a non-static member
function? No, since you don't need an object to call it. Is it
a member function? Yes, because the standard says so (and I
don't know what else you would call it).

The standard is more than confusing about this.
And, still pedantically, it depends on the meaning of the word
"call": for a source code level call that is only evaluated at
compile time you don't need an object; indeed there is no
object at compile time. ;-)
:).
[...]
The C++ syntax for calling a constructor on existing
storage is the basic placement new, like, for emulating
what you're trying to do above,
#include <new>
...
this->A::~A(); // Must first be destroyed.
Technically, only if it has a non-trivial destructor.
(Also, this->A::~A() is probably not a good idea, since the
qualified id prevents virtual function resolution.
In this case qualified destructor call is IMHO the only
reasonable idea, the least ungood. For it's UB to resurrect
the object as an object of different type if it's accessed as
the original type. And so one does, in practice, need to know
the exact most derived type, and that should be expressed in
the code.

Which is more black? In this case, I don't think either are
acceptable:). One thing is sure, calling A::~A() if the
dynamic type of the object is not A will result in undefined
behavior, regardless of the context. For the rest, I can't
think of a case off hand where it would make sense to explicitly
call the destructor where the dynamic type of the object wasn't
the same as the static type; the only times I've used explicit
destructor calls is in my pre-standard implementation of ArrayOf
and ListOf, and like the standard std::vector and std::list (and
C style arrays), they used copy semantics, and didn't allow
derived objects in the container.
 
A

Alf P. Steinbach

* James Kanze:
Note that you've just changed the meaning of "direct".

Depends on what meaning one assumes to begin with. For a constructor the call
via pointer meaning doesn't apply. So it must be something else. Having the call
deferred to the inside of some construct is something else. Ergo, that's it. :D


[snip]
There's no forwarding that I can see.

Well that was perhaps Very Bad Phrasing. Instead of /is/ I should have written
/may be/, I'm sorry. The Holy Standard discusses this in §5.3.4/21, where it
states that it's unspecified whether the allocation function is called before or
after evaluating the specified constructor arguments. If it's called after, then
you can't emulate the effect in C++ level code without argument forwarding.

As an example of emulation, consider

T* p = new T( e1, e2, e3 );

With the allocation function called before the argument evaluation, the compiler
can translate that to machine code equivalent to

T* p;
{
T* __p = (T*)::eek:perator new( sizeof( T ) ); // Or T's allocator.
try
{
::new( __p ) T( e1, e2, e3 );
p = __p;
}
catch( ... )
{
::eek:perator delete( __p ); // Or T's deallocator.
throw;
}
}

With a class-defined allocation function with extra arguments (a placement
allocation function) then on a constructor exception the corresponding placement
deallocation function needs to be called with the same arguments. Which with the
equivalence code above makes it necessary to hold on to those arguments until
sucessful construction has been accomplished. Then the question is, is it easier
or more efficient or whatever to hold on to (effectively forward) the allocation
function arguments, which means calling the allocation function before the
constructor argument evaluation as above, or to hold on to (effectively forward)
the constructor arguments, which means calling the allocation function after the
constructor argument evaluation? The implementation decides.

Anyway, I think of the choice of allocation after the constructor argument
evaluation, as an indirect call of the constructor -- it is similar to calling
f() by calling g() which calls f(), except that one needs C++0x to actually
express at the C++ level a g() that does what operator new does (hm, I'm not
sure whether it's possible even in C++0x for a placement allocation function!).

Cheers,

- Alf
 
J

James Kanze

* James Kanze:
Depends on what meaning one assumes to begin with. For a
constructor the call via pointer meaning doesn't apply. So it
must be something else.

Your assuming the conclusion. A constructor is a function, of
sorts. For a function, a "direct" call means that it doesn't go
through a pointer to a function (usually). In that sense,
constructors can only be called directly. But other meanings of
"direct" can be considered.
Having the call deferred to the inside of some construct is
something else. Ergo, that's it. :D

Or given that () is the function call operator, at the syntax
levbel, using the function call operator is direct, anything
else is indirect (although I'd use explicit/implied here). Of
course, this definition leads to a lot of fun, because () aren't
only function call operators; they can occur in a lot of other
contexts as well.

IMHO, from a syntax point of view, the only reasonable meaning
for a direct call is one that corresponds to what is described
in §5.2.2---that's what the standard identifies as a function
call. In that sense, you can't call the constructor (or the
destructor) explicitly. Except that the standard also speaks of
a "pseudo destructor call" in §5.2.4. (Does the pseudo mean
that it isn't really a call?) The standard also speaks of
"calling the constructor" in several other places---do these
mean that there is something called a "constructor call"
(different from a "function call"), or is the standard just
referring to indirect calls. (There's no doubt that
constructors do get called.)

It's all really word games, and you can argue just about any
point you like, by defining or using the words in special ways.
[snip]
There's no forwarding that I can see.
Well that was perhaps Very Bad Phrasing. Instead of /is/ I
should have written /may be/, I'm sorry. The Holy Standard
discusses this in §5.3.4/21, where it states that it's
unspecified whether the allocation function is called before
or after evaluating the specified constructor arguments. If
it's called after, then you can't emulate the effect in C++
level code without argument forwarding.

Nonsense. Its basically the same case as:

T::constructor( ::eek:perator new( sizeof( T ) ),
arg1,
arg2... ) ;

In practice, under the hood, the allocator is just an
additional, hidden argument to the constructor. I wouldn't call
that "forwarding".

But I'm not sure what you mean by forwarding. That's why I ask.
To me, forwarding would mean that the constructor was somehow
called from the allocator function, or that there was some
special hidden function which called both of them. But that's
not the case, and I'm pretty sure you know that. (The wording in
the standard is there to allow implementations like that in
CFront, where the call to the allocator was actually in the
constructor---if the hidden constructor argument with the
address was null, the constructor called the allocator
function.)
As an example of emulation, consider
T* p = new T( e1, e2, e3 );
With the allocation function called before the argument
evaluation, the compiler can translate that to machine code
equivalent to
T* p;
{
T* __p = (T*)::eek:perator new( sizeof( T ) ); // Or T's allocator..
try
{
::new( __p ) T( e1, e2, e3 );
p = __p;
}
catch( ... )
{
::eek:perator delete( __p ); // Or T's deallocator..
throw;
}
}
With a class-defined allocation function with extra arguments
(a placement allocation function) then on a constructor
exception the corresponding placement deallocation function
needs to be called with the same arguments. Which with the
equivalence code above makes it necessary to hold on to those
arguments until sucessful construction has been accomplished.
Then the question is, is it easier or more efficient or
whatever to hold on to (effectively forward) the allocation
function arguments, which means calling the allocation
function before the constructor argument evaluation as above,
or to hold on to (effectively forward) the constructor
arguments, which means calling the allocation function after
the constructor argument evaluation? The implementation
decides.

I don't get where "effectively holding on to the constructor
arguments" implies forwarding. The compiler generates machine
code, not C++. And the machine code for a function call is
basically: allocate memory for the arguments if necessary,
construct the arguments, then call the function. Those are
three distinct operations, and there's no problem slipping a
call to the allocator anywhere in the middle. And of course,
the presense of a try/catch block doesn't change anything, but
normally, a try/catch block does not generate any inline code.

(Note too that the CFront strategy still works with the required
exception handling. Just that the try/catch block is in the
constructor, not in the calling code.)
Anyway, I think of the choice of allocation after the
constructor argument evaluation, as an indirect call of the
constructor -- it is similar to calling f() by calling g()
which calls f(), except that one needs C++0x to actually
express at the C++ level a g() that does what operator new
does (hm, I'm not sure whether it's possible even in C++0x for
a placement allocation function!).

It's the placement allocation which causes problems for the
CFront model. Placement allocation probably must be done
outside of the constructor. (I can think of an implementation
technique with it in the constructor, but it is heavy and much
more complicated.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top