Search code examples
c++boostc++20gcc10

Boost bimap fails to compile with gcc 10, c++20. Looking for temporary fix


With gcc 10.1 and boost 1.73.0, the following code

#include <boost/bimap.hpp>

int main() {
  boost::bimap<int, int> lookup;
}

fails to compile with flags -O2 --std=c++20, but will succeed with flags -O2 -std=c++17 (verified with compiler explorer).

This is possibly related to the following issue: https://github.com/boostorg/bimap/pull/15 (deprecated std::allocator<void>)

Is there some workaround I can use for now to get this code to successfully compile with --std=c++20?


Solution

  • The reason behind the error is not that the std::allocator<void> specialization is removed. Actually, it's still valid as the primary template with the void argument. The code fails to compile, because ::rebind is no longer part of std::allocator itself. Instead, an implementation should use std::allocator_traits<Alloc>::rebind_alloc<U>.

    Fortunately, most containers usually allow to specify a custom allocator as a template argument. It's also the case for boost::bimap, where an allocator can be the third, fourth or fifth template parameter, according to docs. It defaults to std::allocator, but instead, boost::container::allocator can be used, which does not produce the error:

    #include <boost/bimap.hpp>
    #include <boost/container/allocator.hpp>
    
    int main() {
      boost::bimap<int, int, boost::container::allocator<int>> lookup;
    }
    

    This issue has recently been fixed in 6fba6e5. boost::bimap now properly detects if a nested ::rebind is available:

    template<class A, class T, class = void>
    struct allocator_rebind {
        typedef typename detail::alloc_to<A, T>::type type;
    };
    
    template<class A, class T>
    struct allocator_rebind<A, T,
        typename detail::alloc_void<typename A::template rebind<T>::other>::type> {
        typedef typename A::template rebind<T>::other type;
    };