Log in

View Full Version : c++ vector issues



Trinithis
11-26-2007, 01:07 AM
I am trying to make a derivable Enum class for typesafe enums. The main purpose of the class (so far) is to hold references of each enum in a static vector-like class so one can iterate over all the enums in a loop. So for something like:


for(int i=0; i<Direction::values().size(); ++i) //size is 0 (should be 4)
std::cout << Direction::values()[i]->toString();


The problem is that the vector works perfectly fine inside the constructor of the Enum class, but it "seems" to empty its contents after all the enums have been created. Just to be sure my logic was fine, I replaced the vector with a dummy array, and that worked. But using an array is not very nice to work with because the vector needs to expand.

The actual class I am using for the vector is a class that wraps one and only allows pushing and read-only access. The user aquires this object through an accessor method that puts a const modifier to it so the user cannot push duplicate enums onto its list.

I've spent too long trying to figure out what I've done wrong, so if anyone is willing, here's my code. My dummy concrete enum class is Direction, which has north, east, south, and west.

Enum.h


#ifndef ENUM_H_
#define ENUM_H_

#include <vector>

template <class T> class Enum;

template <class T>
class EnumVector {
public:
void push(const T* o);
const T* at(int i) const;
const T* operator[](int i) const;
int size() const;
friend class Enum<T>;
private:
EnumVector() {}
std::vector<const T*> v;
};

template <class T>
class Enum {
public:
virtual ~Enum() {}
virtual int compareTo(const T* o) const;
virtual std::string name() const;
virtual int ordinal() const;
virtual std::string toString() const;
static const T* valueOf(const std::string name);
static const EnumVector<T> values();
protected:
Enum(std::string name);
int _ordinal;
private:
const std::string _name;
static EnumVector<T> _values;
static int defaultOrdinal;
};

#include "Enum.cpp"

#endif


Enum.cpp


#include "Enum.h"

/*
*
* EnumVector<T>
*
*/

template <class T>
inline void EnumVector<T>::push(const T* o) {
v.push_back(o);
}

template <class T>
inline const T* EnumVector<T>::at(int i) const {
return v.at(i);
}

template <class T>
inline const T* EnumVector<T>::operator[](int i) const {
return v[i];
}

template <class T>
inline int EnumVector<T>::size() const {
return v.size();
}

/*
*
* Enum<T>
*
*/

template <class T>
EnumVector<T> Enum<T>::_values;

template <class T>
int Enum<T>::defaultOrdinal = 0;

template <class T>
Enum<T>::Enum(std::string name):
_ordinal(defaultOrdinal++), _name(name) {
_values.push((const T*)this);
}

template <class T>
int Enum<T>::compareTo(const T* o) const {
if(_ordinal > o->_ordinal) return 1;
else if(_ordinal < o->_ordinal) return -1;
return 0;
}

template <class T>
std::string Enum<T>::name() const {
return (std::string)_name;
}

template <class T>
int Enum<T>::ordinal() const {
return _ordinal;
}

template <class T>
std::string Enum<T>::toString() const {
return (std::string)_name;
}

template <class T>
const T* Enum<T>::valueOf(const std::string name) {
for(int i=_values.size()-1; i>=0; --i)
if(_values[i]->name()==name) return _values[i];
throw "Illegal Argument";
}

template <class T>
inline const EnumVector<T> Enum<T>::values() {
return _values;
}


Direction.h


#ifndef DIRECTION_H_
#define DIRECTION_H_

#include "Enum.h"

class Direction: public Enum<Direction> {
private:
Direction(std::string name);
virtual ~Direction() {}
public:
static const Direction* NORTH;
static const Direction* EAST;
static const Direction* SOUTH;
static const Direction* WEST;
};

#include "Direction.cpp"

#endif


Direction.cpp


#include "Direction.h"

Direction::Direction(std::string name):
Enum<Direction>(name) {}

const Direction* Direction::NORTH = new Direction("north");
const Direction* Direction::EAST = new Direction("east");
const Direction* Direction::SOUTH = new Direction("south");
const Direction* Direction::WEST = new Direction("west");


main.cpp


#include <iostream>
#include "Direction.h"

int main() {
for(int i=0; i<Direction::values().size(); ++i) //size is 0 (should be 4)
std::cout << Direction::values()[i]->toString();
return 0;
}