compile time error due to changes in stl_list.h code

F

fimarn

I am trying to get rid of compile time error that I am getting only in
RHEL5
(not in RHEL4) apparently due to the changes in the stl_list.h file.
The error that I am getting is coming from the following code that
attempts
to remove an item from the list:

class shm_objptr_list : public std::list < void*, SharedMemAlloc<void
*> >
{
.....
bool remove(void *data) {
iterator l_iter = find(data);

if(l_iter == end()) return false;
erase(l_iter); // <=== Compiler flags this line
return true;
}

========================
The allocator is declared as :

template<class T>
class SharedMemAlloc {

public:
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;
typedef T value_type;


template <class _T> struct rebind {
typedef SharedMemAlloc<_T> other;
};

static pointer allocate(size_type n)
{
return (pointer)SharedMemObj::allocate(n);
}
static void deallocate(void* p, size_type n)
{
SharedMemObj::deallocate(p, n);
}

void construct(pointer p, const T&val) {new (p) T(val); }
void destroy(pointer p) {p->~T(); }

};
==============================================
The error looks like this:


/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/
bits/stl_list.h:
In member function typename _Alloc::rebind<_Tp >::eek:ther
std::_List_base<_Tp,
_Alloc>::_M_get_Tp_allocator() const [with _Tp = void*, _Alloc =
SharedMemAlloc<std::_List_node<void* > >]:

/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/
bits/stl_list.h:1149:
instantiated from void std::list<_Tp, _
Alloc>::_M_erase(std::_List_iterator<_Tp>) [with _Tp = void*, _Alloc =
SharedMemAlloc<std::_List_node<void*> >]

/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/
bits/list.tcc:98:
instantiated from 'typename std::list<_Tp, _ Alloc>::iterator
std::list<_Tp,
_Alloc>::erase(std::_List_iterator<_Tp>) [with _Tp = void*, _Alloc =
SharedMemAlloc<std::_List_node <void*> >]'
shmcont.h:71: instantiated from here

/usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/
bits/stl_list.h:327:
error: conversion from 'const SharedMemAllo c said:
non-scalar type 'sharedMemAlloc<void*>' requested
============================================================

I noticed that in a new stl_list.h we have the following:
-----------------------------------------------------------
typedef typename _Alloc::template rebind said:
_Node_alloc_type;

typedef typename _Alloc::template rebind<_Tp>::eek:ther
_Tp_alloc_type;

Tp_alloc_type
_M_get_Tp_allocator() const
{ return *static_cast said:
_M_impl); }

allocator_type
get_allocator() const
{ return _M_get_Tp_allocator(); }
----------------------------------------------------------------

while in the old one:
----------------------------------------------------------------
typedef typename _Alloc::template rebind<_List_node<_Tp> >::eek:ther

_Node_Alloc_type;
allocator_type
get_allocator() const
{ return allocator_type(*static_cast<const
_Node_Alloc_type*>(&this->_M_impl)); }
-----------------------------------------------------------------

I do not know how to change my declaration of the allocator to allow
conversion required by the new header file.

-- FR
 
M

Milburn Young

fimarn said:
I am trying to get rid of compile time error that I am getting only in
RHEL5
(not in RHEL4) apparently due to the changes in the stl_list.h file. ....
============================================================

I noticed that in a new stl_list.h we have the following:
-----------------------------------------------------------

_Node_alloc_type;

typedef typename _Alloc::template rebind<_Tp>::eek:ther
_Tp_alloc_type;

Tp_alloc_type
_M_get_Tp_allocator() const


allocator_type
get_allocator() const
{ return _M_get_Tp_allocator(); }
----------------------------------------------------------------

while in the old one:
----------------------------------------------------------------
typedef typename _Alloc::template rebind<_List_node<_Tp> >::eek:ther

_Node_Alloc_type;
allocator_type
get_allocator() const
{ return allocator_type(*static_cast<const
_Node_Alloc_type*>(&this->_M_impl)); }
-----------------------------------------------------------------

I do not know how to change my declaration of the allocator to allow
conversion required by the new header file.

-- FR

I love your use of 'l_' to prefix local variables. You also did a
good job of converting the code for the outside world (but I spotted
two anomalies ;-). It actually took me over 5 minutes to find the
problem, but I understand why you posted as little as you did. The
problem in your new stl_list is:
_Tp_alloc_type
_M_get_Tp_allocator() const
{ return *static_cast said:
_M_impl); }
should read
_Node_alloc_type
_M_get_Tp_allocator() const
{ return *static_cast said:
_M_impl); }
Also, make sure 'allocator_type' is typedef'd as '_Node_alloc_type',
not '_Tp_alloc_type'. I think Red Hat needs to fix that pronto...I
wonder how std::allocator even works with it the way it is.

Regards,
Milburn Young
 
J

James Kanze

fimarn said:
I am trying to get rid of compile time error that I am getting
only in RHEL5 (not in RHEL4) apparently due to the changes in
the stl_list.h file. The error that I am getting is coming
from the following code that attempts to remove an item from
the list:

[...]
========================
The allocator is declared as :
template<class T>
class SharedMemAlloc {

public:
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;
typedef T value_type;


template <class _T> struct rebind {
typedef SharedMemAlloc<_T> other;
};

static pointer allocate(size_type n)
{
return (pointer)SharedMemObj::allocate(n);
}
static void deallocate(void* p, size_type n)
{
SharedMemObj::deallocate(p, n);
}

void construct(pointer p, const T&val) {new (p) T(val); }
void destroy(pointer p) {p->~T(); }
};

You're missing the conversion constructor. In the standard
allocator, it's a:

template< typename U > allocator( allocator< U > const& ) ;

but if I understand the requirements correctly, all that is
required is that:

Allocator< T > a( b ) ;

is legal, where b has a type Allocator< U >, with U different
from T. (So a conversion operator or an explicit constructor
would be legal. But I'd follow the model of the standard
allocator; I'd guess that very few, if any, implementations are
tested with anything really exotic.)

PS: I've not tried to test with this added to your allocator,
but it looks like a likely cause. And did you compile with
"-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC"? I have no idea if this would help,
but I rather think that if you didn't get an error at the first
attempt to instantiate the template (i.e. when you use it as a
base class, in the header), the people at g++ would probably
consider this an error, and try to fix it in a future release.
 
F

fimarn

fimarn said:
I am trying to get rid of compile time error that I am getting
only in RHEL5 (not in RHEL4) apparently due to the changes in
the stl_list.h file. The error that I am getting is coming
from the following code that attempts to remove an item from
the list:
[...]





========================
The allocator is declared as :
template<class T>
class SharedMemAlloc {
public:
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;
typedef T value_type;
template <class _T> struct rebind {
typedef SharedMemAlloc<_T> other;
};
static pointer allocate(size_type n)
{
return (pointer)SharedMemObj::allocate(n);
}
static void deallocate(void* p, size_type n)
{
SharedMemObj::deallocate(p, n);
}
void construct(pointer p, const T&val) {new (p) T(val); }
void destroy(pointer p) {p->~T(); }
};

You're missing the conversion constructor. In the standard
allocator, it's a:

template< typename U > allocator( allocator< U > const& ) ;

but if I understand the requirements correctly, all that is
required is that:

Allocator< T > a( b ) ;

is legal, where b has a type Allocator< U >, with U different
from T. (So a conversion operator or an explicit constructor
would be legal. But I'd follow the model of the standard
allocator; I'd guess that very few, if any, implementations are
tested with anything really exotic.)

PS: I've not tried to test with this added to your allocator,
but it looks like a likely cause. And did you compile with
"-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC"? I have no idea if this would help,
but I rather think that if you didn't get an error at the first
attempt to instantiate the template (i.e. when you use it as a
base class, in the header), the people at g++ would probably
consider this an error, and try to fix it in a future release.

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- Hide quoted text -

- Show quoted text -

I am not sure if I understand your suggestion. My allocators name is
SharedMemAlloc, so do I do the conversion that you suggested:

Allocator< T > a( b ) ;

I guess I need to make sure that my allocator handles not only (void
*) argument, but also std::_List_node<void* > >. I do not know how you
write it in C++.

Thanks for your help.
 
J

James Kanze

fimarn said:
I am trying to get rid of compile time error that I am getting
only in RHEL5 (not in RHEL4) apparently due to the changes in
the stl_list.h file. The error that I am getting is coming
from the following code that attempts to remove an item from
the list:
[...]
========================
The allocator is declared as :
template<class T>
class SharedMemAlloc {
public:
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;
typedef T value_type;
template <class _T> struct rebind {
typedef SharedMemAlloc<_T> other;
};
static pointer allocate(size_type n)
{
return (pointer)SharedMemObj::allocate(n);
}
static void deallocate(void* p, size_type n)
{
SharedMemObj::deallocate(p, n);
}
void construct(pointer p, const T&val) {new (p) T(val); }
void destroy(pointer p) {p->~T(); }
};
You're missing the conversion constructor. In the standard
allocator, it's a:
template< typename U > allocator( allocator< U > const& ) ;
but if I understand the requirements correctly, all that is
required is that:
Allocator< T > a( b ) ;
is legal, where b has a type Allocator< U >, with U different
from T. (So a conversion operator or an explicit constructor
would be legal. But I'd follow the model of the standard
allocator; I'd guess that very few, if any, implementations are
tested with anything really exotic.)
I am not sure if I understand your suggestion. My allocators name is
SharedMemAlloc, so do I do the conversion that you suggested:
Allocator< T > a( b ) ;

Where? I don't see any user defined constructors or conversion
operators in SharedMemAlloc, and the compiler isn't going to
provide any generic constructor for you.
I guess I need to make sure that my allocator handles not only (void
*) argument, but also std::_List_node<void* > >.

That's what the standard says. You must be able to create an
allocator of type SharedMemAlloc< T1 > by copying an allocator
of type SharedMemAlloc< T0 >. On the other hand, you don't need
to be able to construct an allocator instance from a void*
(which you don't support either); just from an allocator of a
different type.
I do not know how you write it in C++.

It's your allocator, so if you don't know, no one does:).

If the allocator has no state, it is trivial. The template
constructor is empty. If the allocator has the same state for
all allocated types, then that state must be copied. If the
allocator has state which depends on the allocated type, then
you'll have to figure out how to generically map that state.

If the above declaration of SharedMemAlloc is complete, then it
has no state (which sort of surprises me; I'd expect at least a
pointer to the actual object which manages the shared memory).
So just adding:

template< typename U >
SharedMemAlloc( SharedMemAlloc< U > const& ) {}

to the class template definition should do the trick.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top