Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81421 - trunk/boost/heap/detail
From: tim_at_[hidden]
Date: 2012-11-19 07:16:32


Author: timblechmann
Date: 2012-11-19 07:16:31 EST (Mon, 19 Nov 2012)
New Revision: 81421
URL: http://svn.boost.org/trac/boost/changeset/81421

Log:
heap: workaround for msvc lookup bug

attempt to fix #7358
Text files modified:
   trunk/boost/heap/detail/mutable_heap.hpp | 2
   trunk/boost/heap/detail/stable_heap.hpp | 102 +++++++++++++++++++++++++++++++++------
   2 files changed, 86 insertions(+), 18 deletions(-)

Modified: trunk/boost/heap/detail/mutable_heap.hpp
==============================================================================
--- trunk/boost/heap/detail/mutable_heap.hpp (original)
+++ trunk/boost/heap/detail/mutable_heap.hpp 2012-11-19 07:16:31 EST (Mon, 19 Nov 2012)
@@ -382,7 +382,7 @@
     {
         list_iterator it = handle.iterator;
         value_type const & current_value = it->first;
- value_compare const & cmp = q_;
+ value_compare const & cmp = q_.value_comp();
         if (cmp(v, current_value))
             decrease(handle, v);
         else

Modified: trunk/boost/heap/detail/stable_heap.hpp
==============================================================================
--- trunk/boost/heap/detail/stable_heap.hpp (original)
+++ trunk/boost/heap/detail/stable_heap.hpp 2012-11-19 07:16:31 EST (Mon, 19 Nov 2012)
@@ -24,7 +24,6 @@
 namespace heap {
 namespace detail {
 
-
 template<bool ConstantSize, class SizeType>
 struct size_holder
 {
@@ -133,6 +132,8 @@
     {}
 };
 
+// note: MSVC does not implement lookup correctly, we therefore have to place the Cmp object as member inside the
+// struct. of course, this prevents EBO and significantly reduces the readability of this code
 template <typename T,
           typename Cmp,
           bool constant_time_size,
@@ -140,7 +141,9 @@
           bool stable = false
>
 struct heap_base:
+#ifndef BOOST_MSVC
     Cmp,
+#endif
     size_holder<constant_time_size, size_t>
 {
     typedef StabilityCounterType stability_counter_type;
@@ -151,31 +154,47 @@
     typedef Cmp internal_compare;
     static const bool is_stable = stable;
 
+#ifdef BOOST_MSVC
+ Cmp cmp_;
+#endif
+
     heap_base (Cmp const & cmp = Cmp()):
+#ifndef BOOST_MSVC
         Cmp(cmp)
+#else
+ cmp_(cmp)
+#endif
     {}
 
 #ifdef BOOST_HAS_RVALUE_REFS
     heap_base(heap_base && rhs):
+#ifndef BOOST_MSVC
         Cmp(std::move(static_cast<Cmp&>(rhs))),
+#else
+ cmp_(std::move(rhs.cmp_)),
+#endif
         size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))
     {}
 
     heap_base(heap_base const & rhs):
+#ifndef BOOST_MSVC
         Cmp(static_cast<Cmp const &>(rhs)),
+#else
+ cmp_(rhs.value_comp()),
+#endif
         size_holder_type(static_cast<size_holder_type const &>(rhs))
     {}
 
     heap_base & operator=(heap_base && rhs)
     {
- Cmp::operator=(std::move(static_cast<Cmp&>(rhs)));
+ value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
         size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
         return *this;
     }
 
     heap_base & operator=(heap_base const & rhs)
     {
- Cmp::operator=(static_cast<Cmp const &>(rhs));
+ value_comp_ref().operator=(rhs.value_comp());
         size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
         return *this;
     }
@@ -183,7 +202,7 @@
 
     bool operator()(internal_type const & lhs, internal_type const & rhs) const
     {
- return Cmp::operator()(lhs, rhs);
+ return value_comp().operator()(lhs, rhs);
     }
 
     internal_type make_node(T const & val)
@@ -210,17 +229,21 @@
 
     Cmp const & value_comp(void) const
     {
+#ifndef BOOST_MSVC
         return *this;
+#else
+ return cmp_;
+#endif
     }
 
     Cmp const & get_internal_cmp(void) const
     {
- return *this;
+ return value_comp();
     }
 
     void swap(heap_base & rhs)
     {
- std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
+ std::swap(value_comp_ref(), rhs.value_comp_ref());
         size_holder<constant_time_size, size_t>::swap(rhs);
     }
 
@@ -234,15 +257,28 @@
 
     template <typename Heap1, typename Heap2>
     friend struct heap_merge_emulate;
+
+private:
+ Cmp & value_comp_ref(void)
+ {
+#ifndef BOOST_MSVC
+ return *this;
+#else
+ return cmp_;
+#endif
+ }
 };
 
+
 template <typename T,
           typename Cmp,
           bool constant_time_size,
           typename StabilityCounterType
>
 struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
+#ifndef BOOST_MSVC
     Cmp,
+#endif
     size_holder<constant_time_size, size_t>
 {
     typedef StabilityCounterType stability_counter_type;
@@ -251,26 +287,43 @@
     typedef size_holder<constant_time_size, size_t> size_holder_type;
     typedef Cmp value_compare;
 
+#ifdef BOOST_MSVC
+ Cmp cmp_;
+#endif
+
     heap_base (Cmp const & cmp = Cmp()):
- Cmp(cmp), counter_(0)
+#ifndef BOOST_MSVC
+ Cmp(cmp),
+#else
+ cmp_(cmp),
+#endif
+ counter_(0)
     {}
 
 #ifdef BOOST_HAS_RVALUE_REFS
     heap_base(heap_base && rhs):
+#ifndef BOOST_MSVC
         Cmp(std::move(static_cast<Cmp&>(rhs))),
+#else
+ cmp_(std::move(rhs.cmp_)),
+#endif
         size_holder_type(std::move(static_cast<size_holder_type&>(rhs))), counter_(rhs.counter_)
     {
         rhs.counter_ = 0;
     }
 
- heap_base(heap_base & rhs):
- Cmp(static_cast<Cmp&>(rhs)),
- size_holder_type(static_cast<size_holder_type&>(rhs)), counter_(rhs.counter_)
+ heap_base(heap_base const & rhs):
+#ifndef BOOST_MSVC
+ Cmp(static_cast<Cmp const&>(rhs)),
+#else
+ cmp_(rhs.value_comp()),
+#endif
+ size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)
     {}
 
     heap_base & operator=(heap_base && rhs)
     {
- Cmp::operator=(std::move(static_cast<Cmp&>(rhs)));
+ value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
         size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
 
         counter_ = rhs.counter_;
@@ -280,24 +333,22 @@
 
     heap_base & operator=(heap_base const & rhs)
     {
- Cmp::operator=(static_cast<Cmp const &>(rhs));
+ value_comp_ref().operator=(rhs.value_comp());
         size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
 
         counter_ = rhs.counter_;
         return *this;
     }
-
 #endif
 
     bool operator()(internal_type const & lhs, internal_type const & rhs) const
     {
- internal_compare cmp(get_internal_cmp());
- return cmp(lhs, rhs);
+ return get_internal_cmp()(lhs, rhs);
     }
 
     bool operator()(T const & lhs, T const & rhs) const
     {
- return Cmp::operator()(lhs, rhs);
+ return value_comp()(lhs, rhs);
     }
 
     internal_type make_node(T const & val)
@@ -331,7 +382,11 @@
 
     Cmp const & value_comp(void) const
     {
+#ifndef BOOST_MSVC
         return *this;
+#else
+ return cmp_;
+#endif
     }
 
     struct internal_compare:
@@ -355,12 +410,16 @@
 
     internal_compare get_internal_cmp(void) const
     {
- return internal_compare(*this);
+ return internal_compare(value_comp());
     }
 
     void swap(heap_base & rhs)
     {
+#ifndef BOOST_MSVC
         std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
+#else
+ std::swap(cmp_, rhs.cmp_);
+#endif
         std::swap(counter_, rhs.counter_);
         size_holder<constant_time_size, size_t>::swap(rhs);
     }
@@ -379,6 +438,15 @@
     friend struct heap_merge_emulate;
 
 private:
+ Cmp & value_comp_ref(void)
+ {
+#ifndef BOOST_MSVC
+ return *this;
+#else
+ return cmp_;
+#endif
+ }
+
     stability_counter_type counter_;
 };
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk