[heap] typedef T gets prevalence over template parameter

Hi, The d_ary_heap does not compile (in VS2010) when the Comparison class contains a typedef T. The typedef takes prevalence over the template parameter T when the heap is derived from the Comparison class. I.e. the following pattern occurs: template<class T, class Cmp> struct heap_base : Cmp { typedef T value_type; // value_type = Cmp::T } I don't know if this is a bug, a user issue, or a compiler issue. But it caused me a lot of headache when I was trying to apply Jeremiah's indirect_cmp with Boost.Heap. See below for a complete failing example. Kind regards, Alex #include <boost/heap/d_ary_heap.hpp> struct less { typedef int T; bool operator()(const int& a, const int& b) const { return a < b; } }; int main() { boost::heap::d_ary_heap<int, boost::heap::compare<less>, boost::heap::arity<4> > my_heap; return 0; }

The d_ary_heap does not compile (in VS2010) when the Comparison class contains a typedef T. The typedef takes prevalence over the template parameter T when the heap is derived from the Comparison class.
I.e. the following pattern occurs:
template<class T, class Cmp> struct heap_base : Cmp { typedef T value_type; // value_type = Cmp::T }
I don't know if this is a bug, a user issue, or a compiler issue. But it caused me a lot of headache when I was trying to apply Jeremiah's indirect_cmp with Boost.Heap.
hm ... this code works with gcc and with clang ... afaict, msvc does not resolve T correctly. not sure what is the best way to work around this, as every identifier that we can use instead of T could also clash with a declaration in Cmp :/ tim

On 07/09/2012 08:40, Tim Blechmann wrote:
The d_ary_heap does not compile (in VS2010) when the Comparison class contains a typedef T. The typedef takes prevalence over the template parameter T when the heap is derived from the Comparison class.
I.e. the following pattern occurs:
template<class T, class Cmp> struct heap_base : Cmp { typedef T value_type; // value_type = Cmp::T }
I don't know if this is a bug, a user issue, or a compiler issue. But it caused me a lot of headache when I was trying to apply Jeremiah's indirect_cmp with Boost.Heap. hm ... this code works with gcc and with clang ... afaict, msvc does not resolve T correctly.
not sure what is the best way to work around this, as every identifier that we can use instead of T could also clash with a declaration in Cmp :/
tim You could have a workaround like this:
template<typename T, typename U, typename Parent> struct B_args { typedef T T; typedef U U; typedef Parent Parent; }; template<typename T, typename U, typename Parent> struct B : B_args<T, U, Parent> , Parent { typedef typename B_args::T value_type; }; as a replacement for: template<typename T, typename U, typename Parent> struct B : Parent { typedef T value_type; };

On Friday 07 September 2012 10:27:55 Alex Hagen-Zanker wrote:
On 07/09/2012 08:40, Tim Blechmann wrote:
The d_ary_heap does not compile (in VS2010) when the Comparison class contains a typedef T. The typedef takes prevalence over the template parameter T when the heap is derived from the Comparison class.
I.e. the following pattern occurs:
template<class T, class Cmp> struct heap_base : Cmp {
typedef T value_type; // value_type = Cmp::T
}
I don't know if this is a bug, a user issue, or a compiler issue. But it caused me a lot of headache when I was trying to apply Jeremiah's indirect_cmp with Boost.Heap.
hm ... this code works with gcc and with clang ... afaict, msvc does not resolve T correctly.
not sure what is the best way to work around this, as every identifier that we can use instead of T could also clash with a declaration in Cmp :/
tim
You could have a workaround like this:
template<typename T, typename U, typename Parent> struct B_args { typedef T T; typedef U U; typedef Parent Parent; };
template<typename T, typename U, typename Parent> struct B : B_args<T, U, Parent> , Parent { typedef typename B_args::T value_type; };
as a replacement for:
template<typename T, typename U, typename Parent> struct B : Parent { typedef T value_type; };
... or keep Cmp as a member, if possible. Although this would defeat EBO.

On 07/09/2012 10:50, Tim Blechmann wrote:
... or keep Cmp as a member, if possible. Although this would defeat EBO. atm, i'm more thinking of renaming T to a name that is unlikely to be used as member of the Cmp object like BoostHeapValueArgumentWithANameThatHopefullyDoesNotClashWithAnythingOnMsvc
tim That should work. But notice that the inheritence permeates all the way to your main classes and the new name would end up in the public interface and documentation of your library:
template<class T, class ...Options> class d_ary_heap: public detail::select_dary_heap<T, typename detail::d_ary_heap_signature::bind<A0, A1, A2, A3, A4, A5>::type>::type {...
participants (3)
-
Alex Hagen-Zanker
-
Andrey Semashev
-
Tim Blechmann