boostorg / container

STL-like containers from Boost
http://www.boost.org/libs/container/
Boost Software License 1.0
100 stars 116 forks source link

flat_map/flat_set with small_vector as container requires explicit allocator-type #120

Closed tobias-loew closed 5 years ago

tobias-loew commented 5 years ago

The latest changes to the allocator handling in small_vector now requires that the allocator-type has to be specified explicitely when used with flat_map/set:

This line doesn't compile anymore: boost::container::flat_map<int, double, std::less, boost::container::small_vector<std::pair<int, double>,17>> my_map;

But this one does: boost::container::flat_map<int, double, std::less, boost::container::small_vector<std::pair<int, double>,17, boost::container::new_allocator<std::pair<int, double>>>> my_map;

The reason for this is that in container_rebind.hpp:60ff

//Needed for non-conforming compilers like GCC 4.3 template <template <class, std::size_t, class> class Cont, typename V, std::size_t N, typename A, class U> struct container_rebind<Cont<V, N, A>, U> { typedef Cont<U, N, typename allocator_traits::template portable_rebind_alloc::type> type; };

The template doesn't use the "real_allocator" template to figure out the allocator but uses the small_vector's allocator-default "void".

Tobias

tobias-loew commented 5 years ago

Furthermore I came over another problem with custom allocators: I am using the aligned allocator from http://blogs.msdn.com/b/vcblog/archive/2008/08/28/the-aligned_allocator.aspx (from Stephan T. Lavavej) which worked fine with small_vector. But with the step from Boost 1.68 to 1.70 I had to add a specialization

template<std::size_t Alignment>
class aligned_allocator<void, Alignment> {

public:
    typedef void value_type;
    typedef void* pointer;
    typedef const void* const_pointer;

    template<class U>
    struct rebind {
        typedef aligned_allocator<U, Alignment> other;
    };
};

to make the code compile again. I'm using VS 2019, i.e. MSVC 19.20

tobias-loew commented 5 years ago

The container rebind issue seems to be already fix. Thanks

tobias-loew commented 5 years ago

The problem with rebind are due to the non-type template parameter for the alignment of aligned_allocator: the helper-template for doing the rebind only has specializations for class-type templates. Neither gcc, clang or msvc is able to rebind such an allocator with their std::allocator_trait, though I couldn't find any restriction on the kind of template parameters for allocators in the standard. the standard enables automatic rebind only for allocators with only class-type template arguments.

I fixed my problem by replacing the size_t parameter by std::integral_type