473,405 Members | 2,262 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

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 2044
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Carl Bevil | last post by:
Hello all. If I want to use a custom memory manager to, say, track memory allocations in Python, what's the best way to do this? I seem to remember there being a way in version 1.5 (or so -- been...
19
by: regisser | last post by:
I have a quastion for the C++ professionals and members of the C++ standartization commetee. As i know C++ standart requires an allocator to be a templated parameter in every STL container....
12
by: Brian Genisio | last post by:
Hi all, I am developing some software, that creates a tree of information. For each node, currently I am overriding the new operator, because it is a requirement that after initialization, no...
18
by: Mark A. Gibbs | last post by:
I'm having yet another headache with making a standard allocator. What behaviour should be expected from the assigment operator? When would it be called? Why is it there at all, when you can't...
15
by: Alex Vinokur | last post by:
I am looking for any custom allocator sample code for std::vector. Thanks. -- Alex Vinokur http://mathforum.org/library/view/10978.html http://sourceforge.net/users/alexvn
6
by: Ares Lagae | last post by:
Hello, I am trying to create a container the stl way, and I have a couple of questions. The code of the container in question can be found at ...
3
by: Alex Vinokur | last post by:
Compiler GNU g++ version 3.4.4 (cygming special) Custom allocator for vector (see below) checks a return value of 'operator new'. If that value is NULL, the allocator "allocates" no memory....
11
by: Diego Martins | last post by:
for me, these items are in the 'tricky zone' of C++ does anyone know good material with that? (dealing with subtle details, pitfalls, good practices...) anything like the Effective series from...
2
by: mczard | last post by:
Does anyone knows about some open-source custom allocators libarary? I need one especially for fast allocations of elements of a fixed size. This seems to be a very common problem, isn't it?
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.