This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-11


553. Problems with friend allocation and deallocation functions

Section: _N4868_.9.8.2.3  [namespace.memdef]     Status: NAD     Submitter: Dmitriy Litskalov     Date: 16 December 2005

Consider the following example:

    class C {
       public: enum E {};

       friend void* operator new(size_t, E);
       friend void  operator delete(void*, E);
    };

    void foo() {
       C::E e;
       C* ptr = new(e) C();
    }

This code, which is valid in global scope, becomes ill-formed when the class definition is moved into a namespace, and there is no way to make it valid:

    namespace N {
       class C {
          public: enum E {};

          friend void* operator new(size_t, E);
          friend void  operator delete(void*, E);
       };
    }

    void foo() {
       N::C::E e;
       N::C* ptr = new(e) N::C();
    }

The reason for this is that non-member allocation and deallocation functions are required to be members of the global scope (6.7.5.5.2 [basic.stc.dynamic.allocation] paragraph 1, 6.7.5.5.3 [basic.stc.dynamic.deallocation] paragraph 1) , unqualified friend declarations declare names in the innermost enclosing namespace (_N4868_.9.8.2.3 [namespace.memdef] paragraph 3) , and these functions cannot be declared in global scope at a point where the friend declarations could refer to them using qualified-ids because their second parameter is a member of the class and thus can't be named before the class containing the friend declarations is defined.

Possible solutions for this conundrum include invention of some mechanism to allow a friend declaration to designate a namespace scope other than the innermost enclosing namespace in which the friend class or function is to be declared or to relax the innermost enclosing namespace lookup restriction in _N4868_.9.8.2.3 [namespace.memdef] paragraph 3 for friend declarations that nominate allocation and deallocation functions.

Rationale (April, 2006):

The CWG acknowledged that it is not always possible to move code from the global scope into a namespace but felt that this problem was not severe enough to warrant changing the language to accommodate it. Possible solutions include moving the enumeration outside the class or defining member allocation and deallocation functions.