JTC1/SC22/WG21
N0726
Accredited Standards Committee X3 Doc No: X3J16/95-0126 WG21/N0726
Information Processing Systems Date: Jun 30, 1995
Operating under the procedures of Project: Programming Language C++
American National Standards Institute Ref Doc:
Reply to: Josee Lajoie
(josee@vnet.ibm.com)
Issues on Special Member Functions and Proposed Resolutions
===========================================================
*Issue Box 43:
-------------
12[special] paragraph 1 says:
"[Note: ... Often such special member functions are called
implicitly. The processor will implicitly declare these member
functions for a class type when the programmer does not explicitly
declare them."
This text should indicate that implicitly-declared special member
functions can only be called implicitly by the implementation. User
code cannot refer to or define these implicitly-declared special
member functions.
Proposal Box 43:
----------------
I would like to make the following sentence part of the normative text:
"The implementation shall implicitly declare the special member
functions for a class type if the programmer does not explicitly
declare them."
and add the following text:
"An implicitly-declared member function shall not be used
explicitly or defined explicitly in a program. For example,
struct B {
// B() implicitly declared
};
B::B() { } // ill-formed
"
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue 22:
---------
Are access restrictions only limitations on what the programmer may
write?
Must implementations also respect them when implicitly calling the
special member functions?
And if implementations must respect access restriction, when must it
report the errors?
struct B {
private:
~B () { }
};
struct D : public B {
~D () { } // is the mere existence of D::~D considered an
// implicit call of B::~B and therefore a protection
// violation?
};
void f() {
D d; // Or is this an error?
} // Or is the error when d is destroyed?
Proposal 22:
------------
Access restrictions must be respected for implicitly uses of the
special member functions.
Add text to 11 to indicate this.
Paragraph 4 of 11.2 should say
the rules apply to implicit use of special member function as well.
Add to 12.1 after paragraph 5:
"A program is ill-formed if the class for which a default
constructor is explicitly defined has:
-- a nonstatic data member of class type (or array thereof) with
an inaccessible default constructor, or
-- a base class with an inaccessible default constructor."
Add to 12.4 after paragraph 3:
"A program is ill-formed if the class for which a destructor is
explicitly defined has:
-- a non-static data member of class type (or array thereof) with
an inaccessible destructor, or
-- a base class with an inaccessible destructor."
Add to 12.8 after paragraph 6:
"A program is ill-formed if the class for which a copy constructor
is explicitly defined has:
-- a nonstatic data member of class type (or array thereof) with
an inaccessible or ambiguous copy constructor, or
-- a base class with an inaccessible or ambiguous copy constructor."
Add to 12.8 after paragraph 11:
"A program is ill-formed if the class for which a copy assignment
operator is explicitly defined has:
-- a nonstatic data member of class type (or array thereof) with
an inaccessible copy assignment operator, or
-- a base class with an inaccessible copy assignment operator."
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue 379:
----------
How can base class constructors and destructors be used by the
derived class if they are not inherited?
12.1[class.ctor] paragraph 3 says:
"Constructors are not inherited."
12.4[class.dtor] paragraph 6
"Destructors are not inherited."
12.8[class.copy] paragraph 5
"Copy constructors are not inherited."
May a constructor or destructor of a given base class type be invoked
for an object whose type is the derived class type if the invocation
is done using the class-qualified name syntax? If, not, is an
implementation obliged to issue a compile-time diagnostic for such
usage?
struct B {
virtual ~B () { }
};
struct D : public B {
~D () { }
};
D D_object;
D D_object2;
B *B_ptr = &D_object2;
void caller ()
{
D_object.B::~B(); // ok?
B_ptr->~B(); // ok?
}
Discussion 379:
---------------
Regarding the fact that constructor and destructor are not inherited
the ARM says (page 263):
"Consider what might happen if constructors were inherited.
class B {
public:
int a;
B();
B(int);
B(B&);
};
class D : public B {
public:
int b;
};
f() {
B b;
D d1; // only B part initialized
D d2 = b; // only B part of D2 initialized
D d3 = d1; // only B part of D3 initialized
// this is not a copy of derived objects
d3 = 1; // assignment to B part of D
}
... Here, inheriting the constructor from the base class would
quietly change the meaning of copying. The ability to assign
an integer to a D would often be surprising."
We already solve part of this problem when we decided that:
o constructors were not functions but rather a particular syntax
using the class name followed by '()'.
o constructor and destructor is declared (either implicitly declared
or explicitly declared) in every class.
Since a constructor and destructor is declared (either implicitly
declared or explicitly declared) for every class, it is always the
class constructor or destructor that is called when an object of its
class type is created/destroyed. And I believe that the restrictions
in the draft that indicate that constructors and destructors are not
necessary anymore.
Also, because constructors are not member functions, but a special
syntax using the class name, constructors are never inherited. I
believe we should define equivalent semantics for destructors.
(i.e. ~name is a special syntax using the class name anf it causes
the destructor to be invoked...)
Therefore, the syntax:
D_object.B::~B();
or
D_object.~B();
becomes valid if the name of the base class B is accessible in the
class of D_object, and it causes the destructor to be invoked since
the syntax for destructor calls is used.
Proposal 379:
-------------
[change 12.4 to indicate that destructors are not member functions]
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue Box 44:
-------------
When is a default constructor implicitly-defined?
12.1[class.ctor] paragraph 6 says:
"An implicitly-declared default constructor for a class is
implicitly defined when it is used to create an object of its class
type."
Proposal 44:
------------
Add a footnote to say:
"Default constructor are called implicitly to create objects of
automatic storage duration or objects of static storage duration
defined without an initializer (8.5) or are called when the
explicit type conversion syntax (5.2.3) is used."
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue 508:
----------
When is a destructor implicitly-defined?
12.4[class.dtor] paragraph 4 says:
"An implicitly-declared destructor is implicitly defined when it is
used to destroy an object of its class type."
Proposal 508:
-------------
Add a footnote to say:
"Destructors are called implicitly not only when an object of
automatic storage duration goes out of scope, or at the end of a
program for objects with static storage duration, but also in
several situations due to the handling of exceptions."
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue Box 50:
-------------
When is a copy constructor implicitly defined?
Proposal Box 50:
----------------
Add a footnote to 12.8[class.copy] paragraph 7 to say:
"A copy constructor is used to initialize an object of its class
type from a copy of an object of its class type or of a class
derived from its class type. See 8.5 for more details on direct
and copy initialization."
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue Box 47/48:
-----------------
Is a constructor with a parameter of type volatile X& or const
volatile X& a copy constructor?
Must an implicitly-declared copy constructor for class X be able to
copy volatile objects?
[Similar questions for copy assignment operators]
See also paper 95-0056/N0656.
The draft now indicates in footnote 76:
"This implies that the reference parameter of the implicitly-declared
copy constructor cannot bind to a volatile lvalue; see C.2.8."
I do not remember the committee actually voting on this in Austin.
Proposal Box 47/48:
-------------------
Leave things as is ;-)
But describe this implications of this more clearly in 12.8
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue Box 55:
-------------
12.8[class.copy] paragraph 15:
"Whenever a class object is copied and the implementation
can prove that either the original or the copy will never again be
used, an implementation is permitted to treat the original and the
copy as two different ways of referring to the same object..."
The text "can prove that either the original or the copy will never
again be used" needs to be clarified.
Proposal Box 55:
----------------
The sentence above should be rewritten as:
"Whenever a class object is copied into an object of the same type,
and the implementation can prove that either the original or the
copy will never again be used (except for the implicit call of the
destructor at the end of the block or at the end of the program),
an implementation is permitted to treat the original and the copy
as two different ways of referring to the same object..."
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
*Issue S1:
---------
In Message c++std-core-5700, Erwin Unruh writes:
"A return statement in a destructor does not directly return to
the caller. Instead it transfers control to the end of the body
of the destructor. Then the destructors of members and bases are
called. This is the behaviour most (all) of us would expect, but
it is not described in the WP."
Proposal S1:
------------
Add what Erwin says at the end of paragraph 5.
"A return statement in a destructor does not directly return to
the caller. Instead it transfers control to the end of the body
of the destructor. Then the destructors of members and bases are
called."