Does C++11 require allocators to be default constructible, libstdc++ and libc++ disagree?
Asked Answered
P

1

13

Using a slightly modified version of Howard Hinnants's C++11 stack allocator which is documented here and here, with std::basic_string and compiling with gcc which is using libstdc++, the following example (see it live):

const unsigned int N = 200;

arena<N> a;
short_alloc<char, N> ac(a) ;

std::basic_string<char,std::char_traits<char>,short_alloc<char, N>> empty(ac);

gives the following error(amongst others):

error: no matching function for call to 'short_alloc<char, 200ul>::short_alloc()'
   if (__n == 0 && __a == _Alloc())
                       ^

However it works without error when compiling with clang and using libc++ (see it live).

The stdlibc++ implementation of std::basic_string expects the allocator to have a default constructor.

Does C++11 require allocators to be default constructible? Which implementation is correct?

Pomiculture answered 26/3, 2015 at 17:43 Comment(1)
Self-answered questions automatically get a downvote. I have a good idea of who it is, but no evidence. Either way, they need to suck it up because the policy on self-answered questions (it's explicitly encouraged, and there are even GUI options for it!!) has been linked to them many times but they can't seem to accept that.Conlin
P
12

No, C++11 does not require an allocator have default constructor, if we look at the draft C++11 standard section 17.6.3.5 [allocator.requirements] it contains Table 28 Allocator requirements which does not contain a requirement for a default constructor and later on in the section a minimal conforming interface is provided:

[ Example: the following is an allocator class template supporting the minimal interface that satisfies the requirements of Table 28:

template <class Tp>
struct SimpleAllocator {
    typedef Tp value_type;
    SimpleAllocator(ctor args );

    template <class T> SimpleAllocator(const SimpleAllocator<T>& other);

    Tp *allocate(std::size_t n);
    void deallocate(Tp *p, std::size_t n);
};

—end example ]

which does not contain a default constructor.

There is a libstdc++ bug report: basic_string assumes that allocators are default-constructible which says:

The empty-string optimization of basic_string assumes that allocators are default constructible. While this used to be the case in C++98, it is no longer true in C++11, as now allocators are allowed to have state.

Consider the attached example program. Compiling with

g++ -std=c++11 -c t.cpp

produces an error message, even though it should compile fine. The problem is the the "_S_construct" calls "_Alloc()", which does not exist.

Note that the C++11 standard does not require default constructors. (Section 17.6.3.5, Table 28). In particular, the SimpleAllocator example from Section 17.6.3.5 would trigger the same bug, too.

and the response was:

This is hardly the only C++11 allocator requirement missing from std::string, ALL of the new requirements are missing, and unlikely to be implemented until we switch to a non-COW string implementation.

This is fixed as of gcc 5.0:

Fixed for GCC 5 (when using the new string ABI)

We can confirm this using gcc 5 on wandbox

Pomiculture answered 26/3, 2015 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.