Connecting Tech Pros Worldwide Forums | Help | Site Map

Is it the BUG of VC 7.1

Darkay Li
Guest
 
Posts: n/a
#1: Jul 22 '05
I have try to create an allocator like follow:
// the type of allocator must be some kind of pointer
template <class Type>
class PointerAllocator : public std::allocator<Type>
{
public:
typedef std::allocator<Type> BaseClass;

public:
void destroy(pointer ptr)
{
delete (*ptr); // "Type" must be a pointer of object
BaseClass::destroy(ptr);
}
};

My allocator derive from the std::allocator, and just rewrite the destroy
method, to delete the object which the pointer pointer at.
and then I create three containers:
template <class Type>
class PointerList : public std::list<Type, PointerAllocator<Type> >
{
};

template <class Type>
class PointerDeque : public std::deque<Type, PointerAllocator<Type> >
{
};

template<class Key, class Type, class Traits = less<Key> >
class PointerMap : public std::map<Key, Type, Traits,
PointerAllocator<Type> >
{
};
These container can store pointer of the object and free the object it self.

at last I write my test code:
int main(int argc, char* argv[])
{
PointerDeque<int *> pd;
pd.push_back(new int(10));
int *p = pd.front();
cout << *p << endl;

PointerList<int *> pl;
pl.push_back(new int (10));
cout << **pl.begin() << endl;

PointerMap<int , int *> pm;
pm[1] = new int(10);
cout << *pm[1] << endl;

return 0;
}
everything OK when I using VC6 and SGI's STL(both VC6 and VC7.1), but when I
compile the test code with VC7.1(P.J STL) I got error (error message show in
the end). I check the error and find it's the problem of deque's iterator.
In VC7.1 the iterator of deque definition is:
class iterator
: public const_iterator
{ // iterator for mutable deque
public:
//......
iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
: const_iterator(_Off, _Pdeque)
{ // construct with offset _Off in *_Pdeque
}
}
the constructor prototype of iterator is :
iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
and I find it's different from const_iterator's constructor prototype:
const_iterator(size_type _Off, const _Myt *_Pdeque)

Why not use the same definiation of const_iterator?
when I modify the constructor of iterator as the same with const_iterator.
the all my test code compile pass(and run OK).
Is it the BUG of VC7.1 ?

The compile error:
Compiling...
queueTest.cpp
o:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\deque(441) :
error C2665: 'std::deque<_Ty,_Ax>::iterator::iterator' : none of the 3
overloads can convert parameter 2 from type 'std::deque<_Ty,_Ax> *const '
with
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
and
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
o:\Program Files\Microsoft Visual Studio .NET
2003\Vc7\include\deque(241): could be
'std::deque<_Ty,_Ax>::iterator::iterator(std::dequ e<_Ty,_Ax>::size_type,cons
t std::deque<_Ty,std::deque<_Ty,_Ax>::_Alloc> *)'
with
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
while trying to match the argument list
'(std::deque<_Ty,_Ax>::size_type, std::deque<_Ty,_Ax> *const )'
with
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
and
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
o:\Program Files\Microsoft Visual Studio .NET
2003\Vc7\include\deque(440) : while compiling class-template member function
'std::deque<_Ty,_Ax>::iterator std::deque<_Ty,_Ax>::begin(void)'
with
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
d:\SysDir\Documents\Visual Studio
Projects\queueTest\pointercontainer.h(48) : see reference to class template
instantiation 'std::deque<_Ty,_Ax>' being compiled
with
[
_Ty=int *,
_Ax=stk::PointerAllocator<int *>
]
d:\SysDir\Documents\Visual Studio
Projects\queueTest\queueTest.cpp(13) : see reference to class template
instantiation 'stk::PointerDeque<Type>' being compiled
with
[
Type=int *
]




tom_usenet
Guest
 
Posts: n/a
#2: Jul 22 '05

re: Is it the BUG of VC 7.1


On Fri, 19 Dec 2003 09:27:23 +0800, "Darkay Li"
<darkay_li@hotmail.com> wrote:
[color=blue]
>I have try to create an allocator like follow:
> // the type of allocator must be some kind of pointer
> template <class Type>
> class PointerAllocator : public std::allocator<Type>
> {
> public:
> typedef std::allocator<Type> BaseClass;
>
> public:
> void destroy(pointer ptr)
> {
> delete (*ptr); // "Type" must be a pointer of object
> BaseClass::destroy(ptr);
> }
> };
>
>My allocator derive from the std::allocator, and just rewrite the destroy
>method, to delete the object which the pointer pointer at.[/color]

What makes you think that your destroy member will be called? If you
allocator is rebound, the rebound type will be a std::allocator, not
your allocator, and hence your destroy won't be used.

In fact, your allocator doesn't conform to allocator requirements:
Alloc::rebind<U>::other::rebind<T>::other has to be the same as Alloc
(for T). This isn't the case with yours, hence the problems.
[color=blue]
>and then I create three containers:
> template <class Type>
> class PointerList : public std::list<Type, PointerAllocator<Type> >
> {
> };
>
> template <class Type>
> class PointerDeque : public std::deque<Type, PointerAllocator<Type> >
> {
> };
>
> template<class Key, class Type, class Traits = less<Key> >
> class PointerMap : public std::map<Key, Type, Traits,
>PointerAllocator<Type> >
> {
> };
>These container can store pointer of the object and free the object it self.[/color]

Did you actually test this? You may find that your destroy member is
never called.
[color=blue]
>
>at last I write my test code:
>int main(int argc, char* argv[])
>{
> PointerDeque<int *> pd;
> pd.push_back(new int(10));
> int *p = pd.front();
> cout << *p << endl;
>
> PointerList<int *> pl;
> pl.push_back(new int (10));
> cout << **pl.begin() << endl;
>
> PointerMap<int , int *> pm;
> pm[1] = new int(10);
> cout << *pm[1] << endl;
>
> return 0;
>}
>everything OK when I using VC6 and SGI's STL(both VC6 and VC7.1),[/color]

When you say ok, was your destroy function actually called?

but when I[color=blue]
>compile the test code with VC7.1(P.J STL) I got error (error message show in
>the end). I check the error and find it's the problem of deque's iterator.
>In VC7.1 the iterator of deque definition is:
> class iterator
> : public const_iterator
> { // iterator for mutable deque
> public:
> //......
> iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
> : const_iterator(_Off, _Pdeque)
> { // construct with offset _Off in *_Pdeque
> }
> }
>the constructor prototype of iterator is :
>iterator(size_type _Off, const deque<_Ty, _Alloc> *_Pdeque)
>and I find it's different from const_iterator's constructor prototype:
>const_iterator(size_type _Off, const _Myt *_Pdeque)
>
>Why not use the same definiation of const_iterator?[/color]

Well, according to the allocator requirements, _Myt and deque<Ty,
_Alloc> are the same type, so the implementation is allowed to use
them interchangeably.
[color=blue]
>when I modify the constructor of iterator as the same with const_iterator.
>the all my test code compile pass(and run OK).
>Is it the BUG of VC7.1 ?[/color]

No. Your approach isn't going to work. For a start you will have
double deletion problems. Instead I would recommend either writing a
container adapter for pointer holding containers that deletes pointers
when necessary, or use a container<shared_ptr<T> >. e.g.

template <class Cont>
class pointer_container
{
protected:
Cont c;
public:
typedef typename Cont::iterator iterator;
//...
typedef typename Cont::value_type value_type;



void pop_back()
{
delete c.back();
c.pop_back();
}

//etc.
};

Remember that mutating algorithms (like remove_if) will still cause
problems.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Closed Thread