468,738 Members | 1,653 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,738 developers. It's quick & easy.

Custom Allocators question

Hi All,

I'm not sure if I'm dealing with a C++ question or a compiler question,
so please forgive me if I'm asking in the wrong spot. If so, maybe
someone can direct me to more appropriate spot.

In migrating from gcc 3.2.3 to gcc 3.4.3 the following situation comes
up.

I have the following:
//typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;

TestClassVector a;
TestClassVector * tmpVecPtr = &a;
TestClass * tmpPtr = new TestClass(5);
a.push_back(tmpPtr);

if ( (*tmpVecPtr)[0] != NULL )
cout<<"hello main"<<endl;

When using the custom allocator this line breaks:
(*tmpVecPtr)[0] != NULL )

thinking that this field is a TestClass and opposed to the TestClass*
which it should be. If I use the first typedef(with no allocator
specified) it compiles fine with gcc 3.4.3. Also both compile fine
under gcc 3.2.3

I'm not clear if there has been a tightening compliance of the compiler
and i need to add a method to the allocator class to make this compile,
or what exactly my problem is.

If anyone can shed some light on this I would be very appreciative.

Thanks much!
I'll attach the complete code below:

#include <iostream>
#include <vector>

using namespace std;

#ifndef MEMORY_H
#include <memory>
#define MEMORY_H
#endif
template <class T>
class TestAllocator;

template <>
class TestAllocator<void>
{
public:
typedef void* pointer;
typedef const void* const_pointer;

typedef void value_type;

template <class U>
struct rebind
{
typedef TestAllocator<U> other;
};
};

template <class T>
class TestAllocator
{
public:
// Type definitions
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;

typedef T& reference;
typedef const T& const_reference;

pointer address(reference value) const { return &value; }

const_pointer address(const_reference value) const { return &value;
}

// Constructors and destructor
TestAllocator() throw() {}

TestAllocator(const TestAllocator& copy) {}

template <class U>
TestAllocator(const TestAllocator<U>&) throw() {}

~TestAllocator() throw() {}

// Assignment Operator
TestAllocator& operator=(const TestAllocator& rhs) { return *this;
}

inline pointer
allocate(size_type n, const_pointer = 0)
{
pointer p;
size_type size;

size = n * sizeof(T);

p = (pointer) ::operator new(size);

return p;
}
inline void
deallocate(pointer p, size_type n = 1)
{
::operator delete(p);
}

void
construct(pointer p, const T& val)
{
new((void*) p) T(val);
}

void
destroy(pointer p)
{
((T*) p)->~T();
}

size_type
max_size() const throw()
{
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}

template <class U>
struct rebind
{
typedef TestAllocator<U> other;
};
};

class TestClass
{
public:

TestClass(int a): b(a){};
~TestClass();
int getNum() { return b;};

int b;
};

//typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;
int main(int argc, char *argv[])
{
TestClassVector a;
TestClassVector * tmpVecPtr = &a;
TestClass * tmpPtr = new TestClass(5);
a.push_back(tmpPtr);

if ( (*tmpVecPtr)[0] != NULL )
cout<<"hello main"<<endl;
}

Jul 23 '05 #1
15 1777
na**********@yahoo.com wrote:
When using the custom allocator this line breaks:
(*tmpVecPtr)[0] != NULL )


What is the error message?

Jul 23 '05 #2
Ahh.. details!... :)

Switching between the vector definition either w/ or without the
Allocator specified causes it to not match the != NULL. in the case
where an Allocator is specified.

Thanks..

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0l'
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]':

Jul 23 '05 #3
natespama...@yahoo.com wrote:
Switching between the vector definition either w/ or without the
Allocator specified causes it to not match the != NULL. in the case
where an Allocator is specified.

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0l'
!= 0l' ??? What's that?

/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:

x86_64? 64Bit?
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]': TestClass * tmpPtr = new TestClass(5);
Highly questionable. 'new' throws an exception (and doesn't return
NULL) in case of OOM (out-of-memory) according to the C++ Standard (not
actually e.g. in Linux). Anyway ...
if ((*tmpVecPtr)[0] != NULL )


Try:
if ((*tmpVecPtr)[0] != (TestClass*) 0)

Re-think your design!

Jul 23 '05 #4


Panjandrum wrote:
natespama...@yahoo.com wrote:
Switching between the vector definition either w/ or without the
Allocator specified causes it to not match the != NULL. in the case
where an Allocator is specified.

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0l'
!= 0l' ??? What's that?


/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:

x86_64? 64Bit?
yep
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]':
TestClass * tmpPtr = new TestClass(5);


Highly questionable. 'new' throws an exception (and doesn't return
NULL) in case of OOM (out-of-memory) according to the C++ Standard (not
actually e.g. in Linux). Anyway ...
if ((*tmpVecPtr)[0] != NULL )


Try:
if ((*tmpVecPtr)[0] != (TestClass*) 0)


This now spits out:

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0u'
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]':

Re-think your design!


This is just a sample code broken out from the real code that
reproduces the problem in the real code base.

Any other suggestions? Is there something i'm needing to specify in
the allocator that's not there??

Thanks much for the time.

Jul 23 '05 #5
na**********@yahoo.com wrote:
Panjandrum wrote:
Try:
if ((*tmpVecPtr)[0] != (TestClass*) 0)


This now spits out:

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0u'


My last attempt (BTW, I hate STL):

if ((*tmpVecPtr)[(TestClassVector::size_type) 0] != (TestClass*) 0)

Jul 23 '05 #6
Panjandrum wrote:
na**********@yahoo.com wrote:
Panjandrum wrote:
Try:
if ((*tmpVecPtr)[0] != (TestClass*) 0)


This now spits out:

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0u'


My last attempt (BTW, I hate STL):

if ((*tmpVecPtr)[(TestClassVector::size_type) 0] != (TestClass*) 0)


Hmm.no luck either. Many thanks for the suggestions.

I don't think it's along the lines of a cast issue. What's got me
perplexed is why the presence of the custom allocator in the vector
definition causes the compiler to not recognize the operator!=, where
if you take this out, it compiles fine.

Anyone else have any insight/suggestions, i need to get past this
error!

Thanks!

Jul 23 '05 #7
na**********@yahoo.com wrote:
Panjandrum wrote:
na**********@yahoo.com wrote:
Panjandrum wrote:
Try:
if ((*tmpVecPtr)[0] != (TestClass*) 0)
This now spits out:

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0u'

My last attempt (BTW, I hate STL):

if ((*tmpVecPtr)[(TestClassVector::size_type) 0] != (TestClass*) 0)


Hmm.no luck either. Many thanks for the suggestions.

I don't think it's along the lines of a cast issue. What's got me
perplexed is why the presence of the custom allocator in the vector
definition causes the compiler to not recognize the operator!=, where
if you take this out, it compiles fine.

Anyone else have any insight/suggestions, i need to get past this
error!

Thanks!

I've been looking at your problem -- and although I have not yet found a
solution, I do have a suggestion: Look much deeper into the chain of
errors generated -- I think your problem is down the list somewhere.

HTH,
--ag

--
Artie Gold -- Austin, Texas
http://it-matters.blogspot.com (new post 12/5)
http://www.cafepress.com/goldsays
Jul 23 '05 #8
na**********@yahoo.com wrote:

[snip]
I have the following:
//typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;


Forgive me if I'm missing the point, and I'm far from an expert on
allocators, but one would more commonly expect to see the type of the
allocator template specialization match the value_type contained in the
vector. Here, in contrast, you have TestClass* as the value_type of
the vector, but TestClass (i.e., not a pointer) as the type of the
allocator template specialization. In other words, I would have
expected your typedef to read:

typedef std::vector<TestClass*, TestAllocator<TestClass*> >
TestClassVector

or

typedef std::vector<TestClass, TestAllocation<TestClass> >
TestClassVector

but your example seems to meld the two, which looks very strange to me.

But as I said, maybe I've just missed the point.

Best regards,

Tom

Jul 23 '05 #9
> //typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;

int main(int argc, char *argv[])
{
TestClassVector a;
TestClassVector * tmpVecPtr = &a;
TestClass * tmpPtr = new TestClass(5);
a.push_back(tmpPtr);

if ( (*tmpVecPtr)[0] != NULL )
cout<<"hello main"<<endl;
} test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0l'
Looks like operator[] is not returning a TestClass*. Can you try
determining what type it returns? Try something like

TestClass * c = (*tmpVecPtr)[0];

It should tell you something like "cannot convert X to TestClass*".
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]':


What's the rest of the message? Are there other errors?

The code compiles fine on Comeau. Looks like your compiler is broken.
Jonathan

Jul 23 '05 #10


Jonathan Mcdougall wrote:
//typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;

int main(int argc, char *argv[])
{
TestClassVector a;
TestClassVector * tmpVecPtr = &a;
TestClass * tmpPtr = new TestClass(5);
a.push_back(tmpPtr);

if ( (*tmpVecPtr)[0] != NULL )
cout<<"hello main"<<endl;
}
test.cpp: In function `int main(int, char**)':
test.cpp:128: error: no match for 'operator!=' in
'tmpVecPtr->std::vector<_Tp, _Alloc>::operator[] [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>](0ul) != 0l'


Looks like operator[] is not returning a TestClass*. Can you try
determining what type it returns? Try something like

TestClass * c = (*tmpVecPtr)[0];

It should tell you something like "cannot convert X to TestClass*".


Jonathen,

i like that idea...

that line will cause this:

test.cpp: In function `int main(int, char**)':
test.cpp:128: error: cannot convert `TestClass' to `TestClass*' in
initialization
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]':
/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/stl_vector.h:564:
instantiated from `void std::vector<_Tp, _Alloc>::push_back(const
_Tp&) [with _Tp = TestClass*, _Alloc = TestAllocator<TestClass>]'
test.cpp:126: instantiated from here

/usr/lib/gcc/x86_64-redhat-linux/3.4.3/../../../../include/c++/3.4.3/bits/vector.tcc:
In member function `void std::vector<_Tp,
_Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato r<typename
_Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp =
TestClass*, _Alloc = TestAllocator<TestClass>]':
What's the rest of the message? Are there other errors?


Yea there are about 1000 more lines of the stl nonsense that spits out
after that.
For some reason, soon as that allocator is specified, it thinks that
element is the TestClass, not the pointer.
The code compiles fine on Comeau. Looks like your compiler is broken.


Hmmm... I'm wondering if it's a gcc bug possibly? This DOES
compile(with the allocator) w/ gcc 3.2.3...it breaks w/ the 3.4.3

Thanks much for taking the time to compile that! ideas?

Nate

Jul 23 '05 #11


Thomas Tutone wrote:
na**********@yahoo.com wrote:

[snip]
I have the following:
//typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;


Forgive me if I'm missing the point, and I'm far from an expert on
allocators, but one would more commonly expect to see the type of the
allocator template specialization match the value_type contained in the
vector. Here, in contrast, you have TestClass* as the value_type of
the vector, but TestClass (i.e., not a pointer) as the type of the
allocator template specialization. In other words, I would have
expected your typedef to read:

typedef std::vector<TestClass*, TestAllocator<TestClass*> >
TestClassVector

or

typedef std::vector<TestClass, TestAllocation<TestClass> >
TestClassVector

but your example seems to meld the two, which looks very strange to me.

But as I said, maybe I've just missed the point.

Tom

I knew nothing of allocators until i hit this compile problem. My
lightweight understanding of them after my initial investigation, i
came to same conclusion. I'm simply trying to get the codebase to
recompile and wasn't original auther. (this is just a stripped down
sample to post) Seeing as though it did compile(and the work
functionally) with the earlier compiler, my initial assumption was that
perhaps this version was more compliant and i'm just missing something
that needs to be added to allocator. But the returning of different
types strikes me as somewhat more extreme/possible bug?

Maybe i need to dig more into the guts of the real code and see if
there is a design flaw as well.

Thanks for the time!

Jul 23 '05 #12
>> I have the following:
//typedef std::vector<TestClass* > TestClassVector;
typedef std::vector<TestClass*,TestAllocator<TestClass> >
TestClassVector;
Forgive me if I'm missing the point, and I'm far from an expert on
allocators,


Perhaps, but you have got keen eyes.
but one would more commonly expect to see the type of the
allocator template specialization match the value_type contained in the
vector. Here, in contrast, you have TestClass* as the value_type of
the vector, but TestClass (i.e., not a pointer) as the type of the
allocator template specialization. In other words, I would have
expected your typedef to read:

typedef std::vector<TestClass*, TestAllocator<TestClass*> >
TestClassVector

or

typedef std::vector<TestClass, TestAllocation<TestClass> >
TestClassVector

but your example seems to meld the two, which looks very strange to me.


To the OP:
operator[] returns a reference, a typedef which comes from the
allocator. Since you passed a TestClass, the reference was defined as
'TestClass&'. You are trying to convert a 'TestClass&' into a
'TestClass*' which is illegal. Your typedef should be

typedef std::vector<TestClass*,TestAllocator<TestClass*> >;
Jonathan

Jul 23 '05 #13
For grins i actually did match those types up to:
typedef std::vector<TestClass*, TestAllocator<TestClass*> >
TestClassVector

(knowing full well it functionally breaks the real code) and it does
compile now!

SO.... i'm still curious as to why this changed from gcc versions and
if i'm dealing with a C++ or compiler issue ( bug/compliance)

Can anyone that has more experience comment on this, should this not
actually be allowed (mixing the Type vs. the pointer -to)
Thanks

Jul 23 '05 #14
AH.

Ok, thanks for all the insight guys. i appreciate it.

Wonder why this worked(maybe in fact it wasn't) with the previous gcc
version. i'll have to explore this more

Thanks for the time.

Jul 23 '05 #15
Maybe you need to know what vector does. It uses placement new - this
allows it to allocate more space than is needed for its objects without
having to call their constructors (thus reserve(). Even when you don't
call reserve explicitly, it will often reserve when growing).

It gives you the option of the allocator parameter to reduce coupling -
separating the functionality of vector (manipulating multiple objects)
with that of the allocation of memory.

When vector makes a call to its allocator, it wants an address to the
start of memory space to hold N objects. Therefore if its type is T it
wants a T* pointer. So if its type is T* it wants a T** pointer.

C++ is typesafe, so it won't allow you to implicitly convert between T*
and T**. (You need a reinterpret_cast,which is generally a bad idea).

Jul 23 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Carl Bevil | last post: by
19 posts views Thread by regisser | last post: by
12 posts views Thread by Brian Genisio | last post: by
18 posts views Thread by Mark A. Gibbs | last post: by
15 posts views Thread by Alex Vinokur | last post: by
6 posts views Thread by Ares Lagae | last post: by
3 posts views Thread by Alex Vinokur | last post: by
2 posts views Thread by mczard | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
xarzu
2 posts views Thread by xarzu | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.