Document number: N2308=07-0168
Programming Language C++, Library Subgroup
 
Emil Dotchevski, <emil@revergestudios.com>
 
2007-06-10

Adding allocator support to std::function for C++0x

I. Overview

The std::function class template lacks the user-specified allocator support available in its predecessor boost::function. The current definition of boost::function provides a second template parameter that can be utilized to pass a custom allocator class to be used when memory allocations are needed. This second template parameter is optional and defaults to std::allocator.

The main drawback of the allocator support in boost::function is that using a different allocator type leads to different instances of the boost::function class template, even for functions that have the same signature.

This document proposes an alternative approach for custom allocator support for std::function without adding a second template parameter.

II. Motivation

The following are the types of function objects that can be used to initialize a std::function object:

  1. Pointer to function
  2. Pointer to member function
  3. An object of user-defined type that defines suitable operator() member function.

It is possible for std::function implementations to avoid dynamic allocations in the first two cases. In general, dynamic allocations can not be avoided in the third case. The current behavior of std::function in this case is to use new. This precludes its use in contexts where uncontrolled dynamic allocations are not allowed, such as embedded environments.

Note that any use of std::bind with std::function, even when the targeted object is either pointer to function or pointer to member function, leads to the third case and the potential need for dynamic allocations.

The proposed custom allocator support is consistent with the proposed allocator support in shared_ptr (N2232). Both shared_ptr and std::function instances retain source and binary compatibility independently of whether user-defined allocator was used or not.

III. Impact

The allocator support does not add a second parameter to the std::function class template. It has no overhead when no allocator is used.

Even when a custom allocator is supplied, the resulting std::function object is indistinguishable from any other instance of the std::function class template that use the same signature.

The proposed feature affects the interface of std::function, allowing its broader use, and is therefore strongly recommended to be added to the C++0x standard.

IV. Proposed Text

Add to std::function the following constructor:

template <class F,class A>
function( F f, A a );

Requires: f shall be callable for argument types ArgTypes and return type R. A shall be an allocator [allocator.requirements]. The copy constructor and destructor of A shall not throw.

Postconditions: !*this if any of the following hold:

Otherwise, *this targets a copy of f or move(f) if f is not a pointer to member function, and targets a copy of mem_fn(f) if f is a pointer to member function. A copy of a shall be used if dynamic storage must be allocated for the copy of f. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small function objects, e.g., where f’s target is an object holding only a pointer or reference to an object and a member function pointer -- end note.]

Throws: shall not throw exceptions when f is a function pointer or a reference_wrapper<T> for some T. Otherwise, may throw bad_alloc or any exception thrown by F’s copy or move constructor.

Add to std::function the following member function template:

template <class F,class A>
void assign( F f, A a );

Effects: function(f,a).swap(*this);

V. Implementability

A proof of concept implementation is available at:

http://www.revergestudios.com/boost-function

It is expected to be integrated with boost::function in time for the mailing.


Thanks to Peter Dimov and Doug Gregor for reviewing this document.

--end