O
Orjan Westin
Hi,
I have an interesting (read frustrating) problem. I'm writing a
generic container class, which holds data as well as links to other
instances of itself, like this:
template<class T>
class node
{
public:
typedef node<T>* pointer;
typedef T* data_pointer;
typedef std::vector<pointer> nodes;
typedef other_nodes::iterator iterator;
//...
iterator begin() {return _other_nodes.begin();}
//...
private:
pointer _one_node;
nodes _other_nodes;
data_pointer _data;
};
All fine and dandy. However, looking up how to write containers, I
read that any user-defined container is supposed to use the allocator
interface for all storage management, and define an iterator type.
Fine, that's no problem, I thought, especially since I had the
iterator anyway:
template<class T, class A = std::allocator<T> >
class node
{
public:
typedef node<T>* pointer;
typedef A:
ointer data_pointer;
//...
data_pointer data() {return _data;}
//...
private:
pointer _one;
nodes _other_nodes;
data_pointer _data;
};
Still ok.
But.
Do I also need to use the allocator interface to manage my pointers?
If so, I should pass that allocator on to the vector class as well,
right? But since it's a different type, I need a new allocator:
template<class T, class A = std::allocator<T>, class P =
std::allocator<node*> >
class node
{
public:
typedef node<T>* pointer;
typedef std::vector<pointer, P> nodes;
//...
};
Silly me, of course that doesn't work, there are no template
arguments. Let's put one in:
template<class T, class A = std::allocator<T>, class P =
std::allocator<node<T>* > >
class node
{
public:
typedef node<T>* pointer;
typedef std::vector<pointer, P> nodes;
//...
};
And this is where I realised I had problems. Self-referential
declarations? Compiler nesting overload.
What bugs me is that it's ok to use the class inside its own class
declaration, like I do when declaring the vector with the pointers,
but not outside. Yes, of course I understand why, but it took a bit
of thinking.
So, any suggestions? Can I get away with only providing an allocator
interface to the templated class, and use std::allocator internally
for the pointers?
But since I will, on occasion, create another object to point at
internally, I wouldn't be using the allocator interface for that:
template<class T, class A = std::allocator<T> >
class node
{
public:
typedef node<T, A>* pointer;
typedef A::const_reference data_const_reference;
// Assignment constructor taking allocator
node(data_const_reference d, A al = A()) :
_one(NULL),
_alloc(al) {
_data = _alloc.allocate(1);
_alloc.construct(d);}
// Create a new node
void add_one(data_const_reference d) {
pointer p = new node<T, A>(d); // Argh!
_alloc.destroy(_one);
_one = p;}
//...
private:
A _alloc;
pointer _one;
nodes _other_nodes;
data_pointer _data;
};
Help!
//Orjan
I have an interesting (read frustrating) problem. I'm writing a
generic container class, which holds data as well as links to other
instances of itself, like this:
template<class T>
class node
{
public:
typedef node<T>* pointer;
typedef T* data_pointer;
typedef std::vector<pointer> nodes;
typedef other_nodes::iterator iterator;
//...
iterator begin() {return _other_nodes.begin();}
//...
private:
pointer _one_node;
nodes _other_nodes;
data_pointer _data;
};
All fine and dandy. However, looking up how to write containers, I
read that any user-defined container is supposed to use the allocator
interface for all storage management, and define an iterator type.
Fine, that's no problem, I thought, especially since I had the
iterator anyway:
template<class T, class A = std::allocator<T> >
class node
{
public:
typedef node<T>* pointer;
typedef A:
//...
data_pointer data() {return _data;}
//...
private:
pointer _one;
nodes _other_nodes;
data_pointer _data;
};
Still ok.
But.
Do I also need to use the allocator interface to manage my pointers?
If so, I should pass that allocator on to the vector class as well,
right? But since it's a different type, I need a new allocator:
template<class T, class A = std::allocator<T>, class P =
std::allocator<node*> >
class node
{
public:
typedef node<T>* pointer;
typedef std::vector<pointer, P> nodes;
//...
};
Silly me, of course that doesn't work, there are no template
arguments. Let's put one in:
template<class T, class A = std::allocator<T>, class P =
std::allocator<node<T>* > >
class node
{
public:
typedef node<T>* pointer;
typedef std::vector<pointer, P> nodes;
//...
};
And this is where I realised I had problems. Self-referential
declarations? Compiler nesting overload.
What bugs me is that it's ok to use the class inside its own class
declaration, like I do when declaring the vector with the pointers,
but not outside. Yes, of course I understand why, but it took a bit
of thinking.
So, any suggestions? Can I get away with only providing an allocator
interface to the templated class, and use std::allocator internally
for the pointers?
But since I will, on occasion, create another object to point at
internally, I wouldn't be using the allocator interface for that:
template<class T, class A = std::allocator<T> >
class node
{
public:
typedef node<T, A>* pointer;
typedef A::const_reference data_const_reference;
// Assignment constructor taking allocator
node(data_const_reference d, A al = A()) :
_one(NULL),
_alloc(al) {
_data = _alloc.allocate(1);
_alloc.construct(d);}
// Create a new node
void add_one(data_const_reference d) {
pointer p = new node<T, A>(d); // Argh!
_alloc.destroy(_one);
_one = p;}
//...
private:
A _alloc;
pointer _one;
nodes _other_nodes;
data_pointer _data;
};
Help!
//Orjan