This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/15882] Check for return type of overloaded operator new too early
- From: "bangerth at dealii dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 10 Jun 2004 18:22:11 -0000
- Subject: [Bug c++/15882] Check for return type of overloaded operator new too early
- References: <20040608204054.15882.bangerth@dealii.org>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Additional Comments From bangerth at dealii dot org 2004-06-10 18:21 -------
Here is the proposed text for the DR that I have asked Jason to forward for me. Let's
suspend this PR until we hear back about its fate.
W.
----------------------------
Synposis: Wording about templated operator new/delete overly restrictive
Section 3.7.3.1/1 reads:
"[...]The return type shall be void*. The first parameter shall have type
size_t[...] An allocation function can be a function template. Such a
template shall declare its return type and first parameter as
specified above (that is, template parameter types shall not be used in
the return type and first parameter type)."
There are several issues here:
1./ In the parentheses it should probably read "template parameters", since one could also use
template value parameters, not only types.
2./ The wording is overly restrictive. In particular, it disallows the use of the Substitution
Failure is not an Error (SFINAE) pattern to remove certain function templates from the overload
set. It is therefore not possible to write code like this:
template <bool C, typename T> struct SFINAE;
template <typename T> struct SFINAE<true,T> { typedef T type; };
template <typename T> struct ObjectSize {};
template <typename T>
typename SFINAE< (sizeof(T)<=16), void*>
operator new (std::size_t, ObjectSize<T>) {
// call some small object allocator
}
template <typename T>
typename SFINAE< (sizeof(T)>16), void*>
operator new (std::size_t, ObjectSize<T>) {
// call some large object allocator
}
Note that when having a call like in
SomeObject *p = new(ObjectSize<SomeObject>()) SomeObject;
template argument substitution can only be successful for one of the declarations of operator
new, and that in this case the return type evaluates to void* as requested.
3./ The third cited sentence should read "...can be _an instance_ of a function template". This
is also how section 3.7.3.2/2 about operator delete phrases it, which also has issue 1/ correct.
Section 3.7.3.2/2 about operator delete shares the same problem 2/ as above section about
operator new. It has this text:
"A deallocation function can be an instance of a function template.
Neither the first parameter nor the return type shall depend on a
template parameter. [Note: that is, a deallocation function template
shall have a first parameter of type void* and a return type of void
(as specified above). ]"
This text disallows the same mechanism as above for removing signatures from the overload
set.
Proposed resolution:
Replace 3.7.3.1/1 by the following text (changed parts marked):
"An allocation function shall be a class member function or a global
function; a program is ill-formed if an allocation function is
declared in a namespace scope other than global scope or declared
static in global scope. The return type shall be void*. The first
parameter shall have type size_t (_lib.support.types_). The first
parameter shall not have an associated default argument
(_dcl.fct.default_). The value of the first parameter shall be
interpreted as the requested size of the allocation.
__An allocation function can be an instance of a function template.
If template parameter substitution succeeds, the return type shall
evaluate to void*, and the first argument shall evaluate to size_t.__
Template allocation functions shall have two or more parameters."
Replace 3.7.3.2/2 by the following text:
"Each deallocation function shall return void and its first parameter
shall be void*. A deallocation function can have more than one
parameter. If a class T has a member deallocation function named
operator delete with exactly one parameter, then that function is a
usual (non-placement) deallocation function. If class T does not
declare such an operator delete but does declare a member deallocation
function named operator delete with exactly two parameters, the second
of which has type std::size_t (_lib.support.types_), then this
function is a usual deallocation function. Similarly, if a class T
has a member deallocation function named operator delete[] with
exactly one parameter, then that function is a usual (non-placement)
deallocation function. If class T does not declare such an operator
delete[] but does declare a member deallocation function named
operator delete[] with exactly two parameters, the second of which has
type std::size_t, then this function is a usual deallocation function.
A deallocation function can be an instance of a function template.
__If template parameter substitution succeeds, the return type shall
evaluate to void, and the first parameter shall evaluate to void*.__
A deallocation function template shall have
two or more function parameters. A template instance is never a usual
deallocation function, regardless of its signature."
--
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Ever Confirmed| |1
Last reconfirmed|0000-00-00 00:00:00 |2004-06-10 18:22:09
date| |
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15882