3

Unlike STL and std::basic_string, there is no default allocator for std::function. Why?

There is no default allocator for std::function in C++11. But this article(https://learn.microsoft.com/en-us/cpp/standard-library/allocators?view=msvc-160) holds the opposite opinion, which says that:

In C++11 all the Standard Library types and functions that take an allocator type parameter support the minimal allocator interface, including std::function, shared_ptr, allocate_shared(), and basic_string.

template< class Alloc >
function( std::allocator_arg_t, const Alloc& alloc,
              std::nullptr_t ) noexcept;

template<
    class CharT,
    class Traits = std::char_traits<CharT>,
    class Allocator = std::allocator<CharT>
> class basic_string;

template<class T,
class Allocator = std::allocator<T>
> class vector;
Jarod42
  • 203,559
  • 14
  • 181
  • 302
John
  • 2,963
  • 11
  • 33
  • 1
    Isn't the constructor you're asking about removed in C++17? – John Zwinck Dec 25 '20 at 03:56
  • Maybe because the non-allocator versions of these functions would use a "default" allocator? So the only reason to specify it was to override the default? – 1201ProgramAlarm Dec 25 '20 at 04:45
  • @JohnZwinck So, There is no default allocator for `std::function` even in C++11.But this article holds the opposite opinion, which says that:"In C++11 all the Standard Library types and functions that take an allocator type parameter support the minimal allocator interface, including std::function, shared_ptr, allocate_shared(), and basic_string. " – John Dec 25 '20 at 06:10
  • What is your question then? We have no idea why Microsoft wrote that. – John Zwinck Dec 25 '20 at 06:57
  • @JohnZwinck Miscrosoft says that there is a default allocator for `std::function`, but as far as I can see, there is none. – John Dec 25 '20 at 06:59
  • Wording didn't say says `std::function` has default allocator in its type, but (pre-C++17), some `std::function` constructors do take template allocator. – Jarod42 Dec 25 '20 at 11:07

2 Answers2

2

In C++11 and later, the most commonly used non-default constructor is this one:

template<class F> function(F);

I'm going to ignore the others for this discussion because they are less interesting but the same information applies to them.

In C++11 and C++14 it also has this, which was removed in C++20:

template<class F, class Alloc> function(std::allocator_arg_t, const Alloc&, F);

Your question is why it does not have this instead of the above constructor in C++11 and C++14:

template<class F, class Alloc> function(F, const Alloc& = Alloc());

The answer is that there is no way to invoke such a constructor using the default argument, because function(f) always calls the first constructor, and C++ does not have a way to specify the Alloc template parameter. For more on that limitation of C++, see here: Can the template parameters of a constructor be explicitly specified?

Many other types like std::vector are different because their allocator template parameter is on the overall class type, not merely on its constructor.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
1

I assume that you are aware that allocator support in std::function was removed in C++17, so my answer will cover C++11 and C++14, with the caveat that:

std::function's allocator support was poorly specified and inconsistently implemented. Some implementations [did] not provide overloads (6-10) at all, some provide[d] the overloads but ignore[d] the supplied allocator argument, and some provide[d] the overloads and use[d] the supplied allocator for construction but not when the std::function [was] reassigned.

In C++11 and C++14, std::function did not have an allocator template parameter because it was not needed. All the members that would invoke an allocator also accepted an allocator as a function (constructor) template argument; and since std::function performs type erasure on the wrapped callable object, also performing type erasure on an allocator would be straightforward.

In the Microsoft documentation (my emphasis):

In C++11 all the Standard Library types and functions that take an allocator type parameter support the minimal allocator interface, including std::function, [...]

This is referring to the constructors of std::function taking allocator arguments (removed in C++17), which are functions taking an allocator; a constructor is a function in this context.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • You see there is default allocator(i.e `std::allocator`) for `std::vector` and `std::basic_string`.But `std::function` does not have a default allocator. Why? – John Dec 25 '20 at 15:36
  • @John because there's no need for it; the allocator used does not affect the type (since it's erased) and there's no need for the user to know which allocator was used by the constructor not taking `allocator_arg_t`. – ecatmur Dec 26 '20 at 17:10