-->

Boost interprocess flat_map operator[] compilation

2019-09-04 09:08发布

问题:

I'm building some wrapper over the boost::interprocess::flat_map, the problem is, that i'm unable to use operator[] or at for some reason. When i'm using find or insert it compiles succesfully.

typedef boost::interprocess::managed_shared_memory::segment_manager SegmentManager;
typedef boost::interprocess::allocator<char, SegmentManager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>,
        CharAllocator> ShmString;
typedef short KeyType;
typedef ShmString MappedType;
typedef std::pair<const short, ShmString> ValueType;

typedef boost::interprocess::allocator<ValueType,
        boost::interprocess::managed_shared_memory::segment_manager> ShMemAlloc;
typedef boost::interprocess::flat_map<KeyType, MappedType,
        std::less<short>, ShMemAlloc> ShMap;


class Wrapper {

public:

    Wrapper(boost::interprocess::managed_shared_memory* memSeg) :
            m_memSeg(memSeg) {
        const ShMemAlloc initAlloc(m_memSeg->get_segment_manager());
        m_storage = m_memSeg->construct
            <ShMap> (boost::interprocess::anonymous_instance)
            (std::less<KeyType>(), initAlloc);
        ShmString str(initAlloc);
        ValueType val(10, str);

        m_storage->insert(val); //Ok

        ShMap::iterator it = m_storage->find(5); //Ok
        if(it != m_storage->end())
            it->second = str;

        (*m_storage)[5] = str; //Compilation error
    };
    ~Wrapper();

protected:
    boost::interprocess::managed_shared_memory* m_memSeg;

    ShMap* m_storage;
};

It seem's like there is a problem with type deduction in allocator inside the operator[] call, but i have no idea how to use it correctly.

Here is the error report:

../boost/include/boost/container/string.hpp: In instantiation of 'boost::container::container_detail::basic_string_base<Allocator>::members_holder::members_holder() [with Allocator = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]':
../boost/include/boost/container/string.hpp:104:18:   required from 'boost::container::container_detail::basic_string_base<Allocator>::basic_string_base() [with Allocator = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]'
../boost/include/boost/container/string.hpp:596:16:   required from 'boost::container::basic_string<CharT, Traits, Allocator>::basic_string() [with CharT = char; Traits = std::char_traits<char>; Allocator = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]'
../boost/include/boost/container/detail/value_init.hpp:31:13:   required from 'boost::container::container_detail::value_init<T>::value_init() [with T = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >]'
../boost/include/boost/container/flat_map.hpp:846:52:   required from 'boost::container::flat_map<Key, T, Compare, Allocator>::mapped_type& boost::container::flat_map<Key, T, Compare, Allocator>::priv_subscript(const key_type&) [with Key = short int; T = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; Compare = std::less<short int>; Allocator = boost::interprocess::allocator<std::pair<const short int, boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; boost::container::flat_map<Key, T, Compare, Allocator>::mapped_type = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; boost::container::flat_map<Key, T, Compare, Allocator>::key_type = short int]'
../boost/include/boost/container/flat_map.hpp:469:4:   required from 'typename boost::enable_if_c<(((! boost::is_class<BOOST_MOVE_TEMPL_PARAM>::value) || (! boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value)) && (! boost::is_same<Key, BOOST_MOVE_TEMPL_PARAM>::value)), T&>::type boost::container::flat_map<Key, T, Compare, Allocator>::operator[](const BOOST_MOVE_TEMPL_PARAM&) [with BOOST_MOVE_TEMPL_PARAM = int; Key = short int; T = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; Compare = std::less<short int>; Allocator = boost::interprocess::allocator<std::pair<const short int, boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; typename boost::enable_if_c<(((! boost::is_class<BOOST_MOVE_TEMPL_PARAM>::value) || (! boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value)) && (! boost::is_same<Key, BOOST_MOVE_TEMPL_PARAM>::value)), T&>::type = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >&]'
./include/.h:240:23:   required from here
../boost/include/boost/container/string.hpp:218:22: error: no matching function for call to 'boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::allocator()'
../boost/include/boost/container/string.hpp: In instantiation of 'boost::container::container_detail::basic_string_base<Allocator>::members_holder::members_holder() [with Allocator = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]':
../boost/include/boost/container/string.hpp:104:18:   required from 'boost::container::container_detail::basic_string_base<Allocator>::basic_string_base() [with Allocator = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]'
../boost/include/boost/container/string.hpp:596:16:   required from 'boost::container::basic_string<CharT, Traits, Allocator>::basic_string() [with CharT = char; Traits = std::char_traits<char>; Allocator = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >]'
../boost/include/boost/container/detail/value_init.hpp:31:13:   required from 'boost::container::container_detail::value_init<T>::value_init() [with T = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >]'
../boost/include/boost/container/flat_map.hpp:846:52:   required from 'boost::container::flat_map<Key, T, Compare, Allocator>::mapped_type& boost::container::flat_map<Key, T, Compare, Allocator>::priv_subscript(const key_type&) [with Key = short int; T = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; Compare = std::less<short int>; Allocator = boost::interprocess::allocator<std::pair<const short int, boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; boost::container::flat_map<Key, T, Compare, Allocator>::mapped_type = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; boost::container::flat_map<Key, T, Compare, Allocator>::key_type = short int]'
../boost/include/boost/container/flat_map.hpp:469:4:   required from 'typename boost::enable_if_c<(((! boost::is_class<BOOST_MOVE_TEMPL_PARAM>::value) || (! boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value)) && (! boost::is_same<Key, BOOST_MOVE_TEMPL_PARAM>::value)), T&>::type boost::container::flat_map<Key, T, Compare, Allocator>::operator[](const BOOST_MOVE_TEMPL_PARAM&) [with BOOST_MOVE_TEMPL_PARAM = int; Key = short int; T = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >; Compare = std::less<short int>; Allocator = boost::interprocess::allocator<std::pair<const short int, boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > > >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >; typename boost::enable_if_c<(((! boost::is_class<BOOST_MOVE_TEMPL_PARAM>::value) || (! boost::move_detail::is_rv<BOOST_MOVE_TEMPL_PARAM>::value)) && (! boost::is_same<Key, BOOST_MOVE_TEMPL_PARAM>::value)), T&>::type = boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> > >&]'
./include/.h:240:23:   required from here
../boost/include/boost/container/string.hpp:218:22: error: no matching function for call to 'boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>, boost::interprocess::iset_index> >::allocator()'

回答1:

This took some digging. Your problem is that flat_map::operator[] requires the mapped type T to be default constructable because if the object does not exist it needs to be able to insert a default object at that location.

Your ShmString is not default constructable because it doesn't have a default constructable allocator (it has to use the shared memory allocator).

Thus it appears that in your case you will be unable to make use of operator[] and have to use other methods like insert, find, etc.