Topic: operator delete and template instantiation
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/01/14 Raw View
jlilley@empathy.com (John Lilley) writes:
>Hmmm, there is certainly room for discussion here,
Agreed... you've convinced me that the draft is unclear on this issue.
>but think that the
>draft standard is not consistent enough in its use of the specific term
>"requires" to base such a conclusion on its presence or absence in a
>clause.
I'm not suggesting that something must use the word "requires" to
be a requirement. On the contrary, requirements are almost always
stated with the word "shall". Requirements are discussed in
1.3 [intro.compliance] paragraph 5, but I think you would probably
have to look in the ISO standard on standards, where it outlines
the use of the words "should", "shall", etc., for a definition
of what a "requirement" is.
But I don't think you can construe a statement of the form
"if <Foo> is not true, the behaviour is defined." as a requirement.
>Let's look at the corresponding new clause:
>5.3.4 "The new-expression attempts to create an object of the type-id to
>which it is applied. This type shall be a complete nonabstract object
>or array type".
>
>No mention of "required" there.
No, but the use of "shall" clearly expresses a requirement.
>On the other hand, this is clearly undefined bechavior:
>
> template <class T> class A;
> void f(A<int>* ap) { delete ap; }
No, I don't think that's clear at all, by precisely the argument
you have raised! If `delete' is a context that requires a complete
type, then this example is ill-formed, rather than having undefined behaviour,
due to 14.7.1/5:
| 14.7.1 Implicit instantiation [temp.inst]
|
| 5 If an implicit instantiation of a class template specialization is
| required and the template is declared but not defined, the program is
| ill-formed. [Example:
| template<class T> class X;
|
| X<char> ch; // error: definition of X required
| --end example]
--
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
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/01/12 Raw View
comeau@panix.com (Greg Comeau) writes:
>"Martin R\|gamer" <mnruegam@cip.informatik.uni-erlangen.de> writes:
>>template<class T>
>>class A {
>> T t;
>>public:
>> A() : t(T()) {}
>> virtual ~A() {}
>>};
>>
>>A<int> * get_new_A();
>>
>>void main()
>>{
>> A<int> * a_ptr = get_new_A();
>> delete a_ptr; // PC-Lint 7.0: Warning 1404 deleting an object
>> // of type 'A<int>' before type is defined
>>}
>>
>>Is this really an error which means, that in this situation the class
>>A<int> is not instantiated, the destructor A<int>::~A<int> is not
>>instantiated and called (virtual) in main.
Yes, I believe it is. I think PC-Lint is correct here.
>Although it is correct that there are examples where uttering A<int>*
>means that A<int> does not have to be instantiated at that point
>(or at all), I don't see where the problem is here.
The problem here is that this is one of those examples.
| 14.7.1 Implicit instantiation [temp.inst]
|
| 1 [...]
| the class template specialization is implicitly instantiated when the
| specialization is referenced in a context that requires a completely-
| defined object type.
This is not one of those contexts. As I read it, a delete-expression
is not a context that "requires" a completely-defined object type.
The relevant text in [expr.delete]
| 5.3.5 Delete [expr.delete]
|
| 5 If the object being deleted has incomplete class type at the point of
| deletion and the complete class has a non-trivial destructor or a
| deallocation function, the behavior is undefined.
does not mean that a delete-expression of a class type requires a
complete type, it just means that code such as that in the example
program above has undefined behaviour.
--
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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: jlilley@empathy.com (John Lilley)
Date: 1997/01/13 Raw View
Fergus Henderson wrote:
>>> template<class T> class A {
>>> public:
>>> virtual ~A() {}
>>> };
>>> A<int> * get_new_A();
>>>
>>> void main() {
>>> A<int> * a_ptr = get_new_A();
>>> delete a_ptr; // PC-Lint 7.0: Warning 1404 deleting an object
>>> // of type 'A<int>' before type is defined
>>> }
>>> Is this really an error?
> This is not one of those contexts. As I read it, a delete-expression
> is not a context that "requires" a completely-defined object type.
> The relevant text in [expr.delete]
> | 5.3.5 Delete [expr.delete]
> | 5 If the object being deleted has incomplete class type at the point of
> | deletion and the complete class has a non-trivial destructor or a
> | deallocation function, the behavior is undefined.
> does not mean that a delete-expression of a class type requires a
> complete type, it just means that code such as that in the example
> program above has undefined behaviour.
Hmmm, there is certainly room for discussion here, but think that the
draft standard is not consistent enough in its use of the specific term
"requires" to base such a conclusion on its presence or absence in a
clause. To me, saying that the behavior is undefined if you don't have
a complete type, and the compiler has the ability to create a complete
type (by implicitly specializing the template), then that's as good as
having the complete type. That's a central theme of templates -- being
able to instantiate only the needed portions on demand. Furthermore, I
speculate that the ability to call delete on an incomplete type is
solely there for similarity to "C" or perhaps backwards-compatibility
with older CFront. There is no other case where you can invoke an
On the other hand, this is clearly undefined bechavior:
template <class T> class A;
void f(A<int>* ap) { delete ap; }
Let's look at the corresponding new clause:
5.3.4 "The new-expression attempts to create an object of the type-id to
which it is applied. This type shall be a complete nonabstract object
or array type".
No mention of "required" there. But I believe that saying new A<int>
should instantiate A<int>. Of course, you can argue that
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: jlilley@empathy.com (John Lilley)
Date: 1997/01/13 Raw View
Fergus Henderson wrote:
>>> template<class T> class A {
>>> public:
>>> virtual ~A() {}
>>> };
>>> A<int> * get_new_A();
>>>
>>> void main() {
>>> A<int> * a_ptr = get_new_A();
>>> delete a_ptr; // PC-Lint 7.0: Warning 1404 deleting an object
>>> // of type 'A<int>' before type is defined
>>> }
>>> Is this really an error?
> This is not one of those contexts. As I read it, a delete-expression
> is not a context that "requires" a completely-defined object type.
> The relevant text in [expr.delete]
> | 5 If the object being deleted has incomplete class type at the
> | point of deletion and the complete class has a non-trivial
> | destructor or a deallocation function, the behavior is undefined.
> does not mean that a delete-expression of a class type requires a
> complete type, it just means that code such as that in the example
> program above has undefined behaviour.
IMHO, saying that the behavior is undefined if you don't have a complete
type, and the compiler has the ability to create a complete type (by
implicitly specializing the template), then that's as good as having the
complete type. That's a central theme of templates -- being able to
instantiate only the needed portions on demand.
There are other related issues. Consider:
template <class T> class A { A* operator& () {return this; } };
void f(A<char>* ap) {
A<char>& ar = *ap;
ap = &ar;
}
Since "*ap" produces an A<char>& there is still no need to specialize
A<char>, so it is still incomplete. Then, does "&ar" apply the built-in
operator&, producing a still-incomplete A<char>*, or is the specialized
operator& applied, completing A<char> producing an access violation?
The may96 draft says in 5.3.1/4:
"The address of an object of incomplete type can be taken, but if the
complete type of that object is a class type that declares operator&()
as a member function, then the behavior is undefined..."
Which is similar to the clause concerning delete.
The answer, if there is one, may be found (in the may96 draft), at
14.7.1/3:
"If a class template for which a definition is in scope is used in a way
that involves overload resolution, conversion to a base class, or
pointer-to-member conversion, the class template specialization is
implicitly instantiated."
... and in 13.3/2:
"Overload resolution selects the function call in seven distinct
contexts within the language... --invocation of the operator referenced
in an expression (13.3.1.2)"
... and in 13.3.1.2/2:
"If either operand has a type that is a class or an enumeration, a
user-defined operator function might be declared that implements this
operator... In this case, overload resolution is used..."
IMHO, deleting an object involves overload resolution, because the
operator delete is overloaded at the global scope and can be overloaded
at the class scope. This is not completely supported by the above
language, since the operand is not of class type but of type
pointer-to-class. However, I think it is clear from other contexts that
operator delete *does* involve overloading, so this is a moot point.
Perhaps this conlusion is a bit involved, but it seems to get some
support from common-sense (e.g. what I would naturally want and expect
the compiler to do). I draw the same conclusion for operator&() --
since it can be overloaded, then taking the address of an incomplete
class template specialization "involves overload resolution" and thus
requires that the class template specialization be completed.
john lilley
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: "Martin R\|gamer" <mnruegam@cip.informatik.uni-erlangen.de>
Date: 1997/01/08 Raw View
I wrote the following code:
template<class T>
class A {
T t;
public:
A() : t(T()) {}
virtual ~A() {}
};
A<int> * get_new_A();
void main()
{
A<int> * a_ptr = get_new_A();
delete a_ptr; // PC-Lint 7.0: Warning 1404 deleting an object
// of type 'A<int>' before type is defined
}
A<int> * get_new_A()
{
return new A<int>;
}
Is this really an error which means, that in this situation the class
A<int> is not instantiated and the destructor A<int>::~A<int> is not
instantiated and called (virtual) in main.
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Martin R\|gamer" <mnruegam@cip.informatik.uni-erlangen.de>
Date: 1997/01/08 Raw View
I wrote the following code:
template<class T>
class A {
T t;
public:
A() : t(T()) {}
virtual ~A() {}
};
A<int> * get_new_A();
void main()
{
A<int> * a_ptr = get_new_A();
delete a_ptr; // PC-Lint 7.0: Warning 1404 deleting an object
// of type 'A<int>' before type is defined
}
A<int> * get_new_A()
{
return new A<int>;
}
Is this really an error which means, that in this situation the class
A<int> is not instantiated, the destructor A<int>::~A<int> is not
instantiated and called (virtual) in main.
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: comeau@panix.com (Greg Comeau)
Date: 1997/01/10 Raw View
In article <01bbfda8$b4a0f100$f37d0a0a@Mir> "Martin R\|gamer" <mnruegam@cip.informatik.uni-erlangen.de> writes:
>template<class T>
>class A {
> T t;
>public:
> A() : t(T()) {}
> virtual ~A() {}
>};
>
>
>A<int> * get_new_A();
>
>
>void main()
>{
> A<int> * a_ptr = get_new_A();
> delete a_ptr; // PC-Lint 7.0: Warning 1404 deleting an object
> // of type 'A<int>' before type is defined
>}
>
>
>A<int> * get_new_A()
>{
> return new A<int>;
>}
>
>
>Is this really an error which means, that in this situation the class
>A<int> is not instantiated, the destructor A<int>::~A<int> is not
>instantiated and called (virtual) in main.
Although it is correct that there are examples where uttering A<int>*
means that A<int> does not have to be instantiated at that point
(or at all), I don't see where the problem is here.
- Greg
--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C++ 4.0 front-end pre-release
****WEB: http://www.comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
Here:comeau@comeaucomputing.com / BIX:comeau or comeau@bix.com / CIS:72331,3421
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]