Template member function cast bug in VC80SP1 (and more...)



Hi to all,

writing a small piece of metaprogramming code, we had to face some problems:
one at least seems a bug in VC8.0 (SP1).
here's an overview: we have

class VECTOR
class MAP_BASE : private VECTOR
class MAP : public MAP_BASE

MAP_BASE makes public some (originally public) things in VECTOR, such as
VECTOR::erase, and both MAP_BASE and MAP define 'iterator' as
VECTOR::iterator.
we'll omit template parameters from the text, a precise c++ sample is
appended below.




(problem 1: less important)
if we write

typedef MAP::iterator (MAP::*pointer_to_erase_t)(MAP::iterator);
pointer_to_erase_t p = &MAP::erase

every compiler we tried (vc8, gcc4, intel10) says that 'erase' is
inaccessible (in a private base), despite the fact that the member is...
public, due to the using declaration.
actually we had a quick look in the standard, and surprisingly, it just says
'if the member is in a private base, the conversion (of the pointer) fails.
is this an omission?


(problem 2: very important)

is there some way to test if a class has ANY member/member function
named -let's say- swap?
we just need to know if the expression "&T::swap" is legal or not.
first, we tried the following but it seems that it's illegal:

template <typename S>
class has_something_named_swap
{
class yes { char dummy[2]; };
typedef char no;

template <typename T>
static yes test(T*, size_t = sizeof(&T::swap));

static no test(void*, size_t = 0);

public:

static const bool value = sizeof(test( (S*)0 ))!= sizeof(no);
};



the following variant works well in gcc4 and intel10 (and according to the
SFINAE principle, it should work!!!)
but does not compile in vc8 (it says something like: overloaded function,
illegal sizeof operand):


template <size_t N> class yes { char dummy[2]; };

template <typename T>
static yes<sizeof(&T::swap)> test(T*);


I personally think it's an artificial limitation in VC.







(problem 3: very important)
it looks like VC8 is unable to resolve a
pointer-to-overloaded-member-function when some of the overloads are in
VECTOR and some are in MAP_BASE.
Here's a minimal sample that shows the problem: both intel10 and gcc4 do
compile it correctly.
(NOTE: DON'T RUN - IT WILL CRASH - BUT IT SHOULD COMPILE)

the most satisfactory workaround we found is to duplicate VECTOR::erase in
MAP_BASE (it's commented in the code), but as a rule this is not nice (if
also std::map had the same problem, we would have had to overload erase_gap
on std::map, which is exactly what we are trying to avoid...)




#include <map>
#include <vector>


template <typename T>
class VECTOR
{
typedef std::vector<T> vector_t;
vector_t data_;

public:

typedef typename vector_t::iterator iterator;

iterator begin() { return data_.begin(); }

iterator erase(iterator pos)
{
return (pos);
}
};


template <typename key_t, typename mapped_t>
class MAP_BASE : private VECTOR< std::pair<key_t, mapped_t> >
{
public:

typedef VECTOR< std::pair<key_t, mapped_t> > map_t;

typedef typename map_t::iterator iterator;

using map_t::begin;
using map_t::erase;

size_t erase(const key_t& x)
{
return 0;
}

// iterator erase(iterator pos)
// {
// return map_t::erase(pos);
// }

};


template <typename key_t, typename mapped_t>
class MAP : public MAP_BASE<key_t, mapped_t>
{
typedef MAP_BASE<key_t, mapped_t> base_t;

public:

using base_t::iterator;
};


template <typename container_t, typename iterator_t, typename base_t>
inline void erase_gap2(container_t& c, iterator_t& i, iterator_t
(base_t::*)(iterator_t))
{
i = c.erase(i);
}

template <typename container_t, typename iterator_t, typename base_t>
inline void erase_gap2(container_t& c, iterator_t& i, void
(base_t::*)(iterator_t))
{
c.erase(i++);
}

template <typename container_t>
typename container_t::iterator erase_gap(container_t& c, typename
container_t::iterator i)
{
erase_gap2(c, i, &container_t::erase);
return i;
}




int main()
{
std::vector<double> v;
std::map<double, double> m;
MAP<double, double> w;

erase_gap(w, w.begin());
erase_gap(v, v.begin());
erase_gap(m, m.begin());

return 0;
}



.



Relevant Pages

  • traits help
    ... I am learning template programming and there is a problem about ... Now consider a container and an iterator. ... template <typename T> ...
    (comp.lang.cpp)
  • Help Please: Finding out the Iterator to the Child node in binary heap
    ... But I got into trouble finding out the Iterator to the Child node. ... template <typename Iterator, typename Functor> ...
    (comp.lang.cpp)
  • Re: Best way to "redefine" a std class
    ... template <typename T> myList { ... iterator begin ...
    (comp.lang.cpp)
  • Re: Maintance of c++ code
    ... iterator constant in the standard, ... template ... template <class Iter_> ... container, some only work with particular containers. ...
    (comp.object)
  • Re: Einfache Frage zu STD::SORT
    ... > void sort(RanIt first, RanIt last, Pred pr); ... > The first template function reorders the sequence designated by ... >> auch was anderes, je nachdem halt, wie der jeweilige Iterator ... Eben, ein Objekt. ...
    (microsoft.public.de.vc)