Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
418 views
in Technique[技术] by (71.8m points)

c++ - How to overload the assignment operator for strings that use custom allocator

I am trying to use boost MultiIndex container in shared memory, I am using the replace function to update the records, when trying to compile, the compiler complained about the operator = being not present so I have overloaded the operator = as shown in the code below, however it seems that the compilation errors that are being thrown are because of the allocators. This is the first time I am using custom allocator for shared memory. Is there anything special that we need to do while overloading the operator = for strings with custom allocator?

  1 #include <boost/interprocess/managed_shared_memory.hpp>
  2 #include <boost/interprocess/allocators/allocator.hpp>
  3 #include <boost/interprocess/containers/string.hpp>
  4
  5 #include <boost/multi_index_container.hpp>
  6 #include <boost/multi_index/member.hpp>
  7 #include <boost/multi_index/ordered_index.hpp>
  8 #include <iostream>
  9
 10 using namespace boost::interprocess;
 11 namespace bmi = boost::multi_index;
 12
 13 typedef managed_shared_memory::allocator<char>::type              char_allocator;
 14 typedef basic_string<char, std::char_traits<char>, char_allocator> shm_string;
 15
 16 //Data to insert in shared memory
 17 struct tickerUpdateInfo
 18 {
 19   shm_string  id;
 20   shm_string  symbol;
 21   int         last_update_time;
 22
 23   tickerUpdateInfo( const char * id_,
 24       const char *symbol_,
 25       int last_update_time_,
26       const char_allocator &a)
 27     : id(id_, a), symbol(symbol_, a), last_update_time(last_update_time_) {
 28     }
 29
 30   tickerUpdateInfo& operator=(const tickerUpdateInfo& other)
 31   {
 32     if (this != &other) {
 33       id = other.id;
 34       symbol = other.symbol;
 35       last_update_time = other.last_update_time;
 36     }
 37     return *this;
 38   }
 39 };
 40
 41 std::ostream& operator<<(std::ostream& os, const tickerUpdateInfo& obj)
 42 {
 43   // write obj to stream
 44   os << obj.id << " ";
 45   os << obj.symbol << " ";
 46   os << obj.last_update_time << " " << std::endl;
 47   return os;
 48 };
 49
 50
 51 //Tags
 52 struct id{};
 53 struct symbol{};
 54 struct last_update_time{};
 55
 56 // Define a multi_index_container of tickerUpdateInfos with following indices:
 57 //   - a unique index sorted by tickerUpdateInfo::id,
 58 //   - a unique index sorted by tickerUpdateInfo::symbol,
 59 //   - a non-unique index sorted by tickerUpdateInfo::last_update_time.
 60 typedef bmi::multi_index_container<
 61 tickerUpdateInfo,
 62   bmi::indexed_by<
 63   bmi::ordered_unique
 64   <bmi::tag<id>,  BOOST_MULTI_INDEX_MEMBER( tickerUpdateInfo, shm_string, id)>,
 65   bmi::ordered_unique<
 66   bmi::tag<symbol>,BOOST_MULTI_INDEX_MEMBER(tickerUpdateInfo, shm_string, symbol)>,
 67   bmi::ordered_non_unique
 68   <bmi::tag<last_update_time>, BOOST_MULTI_INDEX_MEMBER(tickerUpdateInfo, int, last_update_time)> >,
 69   managed_shared_memory::allocator<tickerUpdateInfo>::type
 70   > tickerUpdateInfo_set;
 71
 72 int main ()
 73 {
 74   //Remove shared memory on construction and destruction
 75   struct shm_remove
 76   {
 77     shm_remove() { shared_memory_object::remove("MySharedMemory"); }
 78     ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
 79   } remover;
 80
 81   //Create shared memory
 82   managed_shared_memory segment(create_only,"MySharedMemory", 65536);
 83
 84   //Construct the multi_index in shared memory
 85   tickerUpdateInfo_set *es = segment.construct<tickerUpdateInfo_set>
 86     ("TickerUpdateContainer")            //Container's name in shared memory
 87     ( tickerUpdateInfo_set::ctor_args_list()
 88       , segment.get_allocator<tickerUpdateInfo>());  //Ctor parameters
 89
 90   //Now insert elements
 91   char_allocator ca(segment.get_allocator<char>());
 92   es->insert(tickerUpdateInfo("0","Joe", 31,ca));
 93   es->insert(tickerUpdateInfo("1", "Robert",27, ca));
 94   es->insert(tickerUpdateInfo( "2","John", 36,ca));
 95   const tickerUpdateInfo_set::nth_index<1>::type& name_index = (*es).get<1>();
 96   std::cout << "Before update " << std::endl;
 97   std::copy(
 98       name_index.begin(),name_index.end(),
 99       std::ostream_iterator<tickerUpdateInfo>(std::cout));
100
101
102   typedef tickerUpdateInfo_set::index<symbol>::type ticker_update_info_set_by_symbol;
103   ticker_update_info_set_by_symbol & nm_index = (*es).get<symbol>();
104   ticker_update_info_set_by_symbol::iterator it=nm_index.find("Joe");
105   tickerUpdateInfo ticker_info = *it;
106   ticker_info.symbol = "Deb";      // update key
107   nm_index.replace(it, ticker_info ); // update her record
108   std::cout << "After update " << std::endl;
109   std::copy(
110       nm_index.begin(),nm_index.end(),
111       std::ostream_iterator<tickerUpdateInfo>(std::cout));
112   return 0;
113 }

Compilation Errors:

   -- Compiling src/writer.cxx
In file included from include/boost/multi_index/ordered_index.hpp:56,
                 from src/writer.cxx:7:
include/boost/multi_index/detail/ord_index_ops.hpp: In constructor 'boost::container::basic_string<CharT, Traits, Alloc>::basic_string(const CharT*, const A&) [with CharT = char, Traits = std::char_traits<char>, A = boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> >]':
include/boost/multi_index/detail/ord_index_ops.hpp:67:   instantiated from 'Node* boost::multi_index::detail::ordered_index_find(Node*, Node*, const KeyFromValue&, const CompatibleKey&, const CompatibleCompare&) [with Node = boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<tickerUpdateInfo, boost::interprocess::allocator<tickerUpdateInfo, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > > >, KeyFromValue = boost::multi_index::member<tickerUpdateInfo, 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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, &tickerUpdateInfo::symbol>, CompatibleKey = char [4], CompatibleCompare = std::less<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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > >]'
include/boost/multi_index/ordered_index.hpp:434:   instantiated from 'boost::multi_index::detail::bidir_node_iterator<boost::multi_index::detail::ordered_index_node<typename SuperMeta::type::node_type> > boost::multi_index::detail::ordered_index<KeyFromValue, Compare, SuperMeta, TagList, Category>::find(const CompatibleKey&) const [with CompatibleKey = char [4], KeyFromValue = boost::multi_index::member<tickerUpdateInfo, 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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, &tickerUpdateInfo::symbol>, Compare = std::less<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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > > >, SuperMeta = boost::multi_index::detail::nth_layer<2, tickerUpdateInfo, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::tag<id, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::member<tickerUpdateInfo, 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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, &tickerUpdateInfo::id>, mpl_::na>, boost::multi_index::ordered_unique<boost::multi_index::tag<symbol, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::member<tickerUpdateInfo, 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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, &tickerUpdateInfo::symbol>, mpl_::na>, boost::multi_index::ordered_non_unique<boost::multi_index::tag<last_update_time, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::member<tickerUpdateInfo, int, &tickerUpdateInfo::last_update_time>, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::interprocess::allocator<tickerUpdateInfo, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> > >, TagList = boost::mpl::v_item<symbol, boost::mpl::vector0<mpl_::na>, 0>, Category = boost::multi_index::detail::ordered_unique_tag]'
src/writer.cxx:107:   instantiated from here
include/boost/multi_index/detail/ord_index_ops.hpp:67: 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::offset_ptr<void>, 0ul>, boost::interprocess::iset_index> >::allocator()'
include/boost/interprocess/allocators/allocator.hpp:130: note: candidates are: boost::interprocess::allocator<T, SegmentManager>::allocator(const boost::interprocess::allocator<T, SegmentManager>&) [with T = char, SegmentManager = boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void>, 0ul>, boost::interprocess::iset_index>]
include/boost/in

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is that ordered_unique/ordered_non_unique indexes use std::less<K> by default. When you search by a compatible key nm_index.find("Joe"), char const[] "Joe" needs to be converted to shm_string in std::less<K>::operator()(shm_string const&, shm_string const&), but shm_string constructor also requires an allocator argument.

The solution is to provide your own compare class that does not convert arguments:

struct Less
{
    template<class T, class U>
    bool operator()(T const& t, U const& u) const {
        return t < u;
    }
};

// Define a multi_index_container of tickerUpdateInfos with following indices:
//   - a unique index sorted by tickerUpdateInfo::id,
//   - a unique index sorted by tickerUpdateInfo::symbol,
//   - a non-unique index sorted by tickerUpdateInfo::last_update_time.
typedef bmi::multi_index_container<
    tickerUpdateInfo,
    bmi::indexed_by<
          bmi::ordered_unique<bmi::tag<id>, BOOST_MULTI_INDEX_MEMBER( tickerUpdateInfo, shm_string, id), Less>,
          bmi::ordered_unique<bmi::tag<symbol>,BOOST_MULTI_INDEX_MEMBER(tickerUpdateInfo, shm_string, symbol), Less>,
          bmi::ordered_non_unique<bmi::tag<last_update_time>, BOOST_MULTI_INDEX_MEMBER(tickerUpdateInfo, int, last_update_time), Less>
          >,
    managed_shared_memory::allocator<tickerUpdateInfo>::type
> tickerUpdateInfo_set;

tickerUpdateInfo& operator=(const tickerUpdateInfo& other) is not required, the compiler generated one does the same thing.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...