>From 942dcd50e2b4fd4a12e405455f7c26ed71a869ce Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 27 Feb 2015 14:46:52 +0100 Subject: [PATCH] Use a sorted vector instead of std::map<> in MemberSymbolTable. This is slightly faster than using a map and, more importantly, provides scope for the upcoming optimizations. --- any_member.hpp | 55 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/any_member.hpp b/any_member.hpp index 70a9e18..8e5f4a6 100644 --- a/any_member.hpp +++ b/any_member.hpp @@ -536,8 +536,7 @@ template class MemberSymbolTable :private lmi::uncopyable > { - typedef std::map > member_map_type; - typedef typename member_map_type::value_type member_pair_type; + typedef std::vector > values_vector_type; public: virtual ~MemberSymbolTable(); @@ -561,12 +560,20 @@ class MemberSymbolTable template void ascribe(std::string const& s, ValueType SameOrBaseClassType::* p2m) { - ClassType* class_object = static_cast(this); - map_.insert - (member_pair_type(s, any_member(class_object, p2m)) - ); typedef std::vector::iterator svi; svi i = std::lower_bound(member_names_.begin(), member_names_.end(), s); + + ClassType* class_object = static_cast(this); + + member_values_.push_back(any_member(class_object, p2m)); + typedef typename values_vector_type::size_type vvs_t; + vvs_t const first = i - member_names_.begin(); + vvs_t const last = member_values_.size() - 1; + for(vvs_t n = last; n != first; --n) + { + swap(member_values_[n - 1], member_values_[n]); + } + member_names_.insert(i, s); } #endif // defined __BORLANDC__ @@ -574,7 +581,7 @@ class MemberSymbolTable private: void complain_that_no_such_member_is_ascribed(std::string const&) const; - member_map_type map_; + values_vector_type member_values_; std::vector member_names_; }; @@ -613,12 +620,13 @@ any_member& MemberSymbolTable::operator[] (std::string const& s ) { - typename member_map_type::iterator i = map_.find(s); - if(map_.end() == i) + typedef std::vector::iterator svi; + svi i = std::lower_bound(member_names_.begin(), member_names_.end(), s); + if(member_names_.end() == i || s != *i) { complain_that_no_such_member_is_ascribed(s); } - return i->second; + return member_values_[i - member_names_.begin()]; } template @@ -626,12 +634,7 @@ any_member const& MemberSymbolTable::operator[] (std::string const& s ) const { - typename member_map_type::const_iterator i = map_.find(s); - if(map_.end() == i) - { - complain_that_no_such_member_is_ascribed(s); - } - return i->second; + return (const_cast&>(*this))[s]; } #if !defined __BORLANDC__ @@ -663,11 +666,25 @@ void MemberSymbolTable::ascribe >::value )); - ClassType* class_object = static_cast(this); - map_.insert(member_pair_type(s, any_member(class_object, p2m))); typedef std::vector::iterator svi; - // TODO ?? This would appear to be O(N^2). svi i = std::lower_bound(member_names_.begin(), member_names_.end(), s); + + ClassType* class_object = static_cast(this); + + // Using the usual insert() method relies on vector elements being + // assignable in C++98, but this is not the case for any_member<>, so we + // append the element at the end and then put it into the right place. + member_values_.push_back(any_member(class_object, p2m)); + typedef typename values_vector_type::size_type vvs_t; + vvs_t const first = i - member_names_.begin(); + vvs_t const last = member_values_.size() - 1; + for(vvs_t n = last; n != first; --n) + { + swap(member_values_[n - 1], member_values_[n]); + } + + // Notice that insert() may invalidate the iterator, so it can only be done + // after using "i" for computing the index into member_values_ above. member_names_.insert(i, s); } #endif // !defined __BORLANDC__ -- 2.1.0