Question

I thought containers have to rebind whatever allocator they are given into an allocator that works, but in STL that ships with LLVM (part of libc++, I guess), this doesn't seem to be the case. Is this a bug in LLVM, or does the standard not require rebinding?

The following snippet works as expected with GCC's STL. It fails with STL that comes with clang 3.3 (from MacPorts, on a Mac). It compiles fine with clang on Linux, but I think that one uses the same STL as GCC.

#include <vector>

int main()
{
    std::vector<char, std::allocator<int> >  c;
    c.push_back(5);
}

The error is

clang++ test-rebind.cpp 
In file included from test-rebind.cpp:1:
/opt/local/libexec/llvm-3.3/bin/../lib/c++/v1/vector:505:5: error: implicit instantiation of undefined template '__static_assert_test<false>'
    static_assert((is_same<typename allocator_type::value_type, value_type>::value),
    ^
/opt/local/libexec/llvm-3.3/bin/../lib/c++/v1/__config:412:35: note: expanded from macro 'static_assert'
    typedef __static_assert_check<sizeof(__static_assert_test<(__b)>)> \
                                  ^
test-rebind.cpp:5:46: note: in instantiation of template class 'std::__1::vector<char, std::__1::allocator<int> >' requested here
    std::vector<char, std::allocator<int> >  c;
                                             ^
/opt/local/libexec/llvm-3.3/bin/../lib/c++/v1/__config:408:24: note: template is declared here
template <bool> struct __static_assert_test;
                       ^
1 error generated.
Was it helpful?

Solution

23.2.1 [container.requirements.general]/7:

All other constructors for these container types take an Allocator& argument (17.6.3.5), an allocator whose value type is the same as the container’s value type.

So your code is invalid.

The above is a rather obscure place to find this, though. We can do better. Table 99 (allocator-aware container requirements) requires in its first row that the container has an allocator_type nested type, whose value_type is identical to the container's. And the synopsis for vector (and the other containers) defines allocator_type thus:

typedef Allocator allocator_type;

In other words, the Allocator parameter you supply is responsible for fulfilling the requirement.

OTHER TIPS

I thought containers have to rebind whatever allocator they are given into an allocator that works

I can’t find that requirement anywhere. Rather, rebind is used if the container needs to allocate something other than value_type. Consider a typical, simplified list implementation:

template <typename T, typename A = std::allocator<T>>
class list {
    struct node {
        T value;
        node* next;
        node* prev;
    };
    using allocator = typename A::template rebind<node>::other;
};

Here we need to use rebind because the list doesn’t allocate Ts; it allocates list<T>::nodes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top