Sign in to follow this  
azherdev

Trying to create a C++ collection class similar to .NET collection

Recommended Posts

azherdev    112
I need some help in creating a general collection class. Internally it will use STL vector. Here is what I have: CCollection.h
#pragma once
#include <vector>

class CCollection
{
public:
	CCollection();
	virtual ~CCollection();

	size_t	add(void *item);
	void	insert(size_t position, void *item);
	void	remove(size_t index);
	void	remove(void *item);
	void	clear(void);
	size_t	count(void);
	void*	at(size_t index);
	void	set(size_t index, void * value);

protected:
	std::vector<void*> m_data;
};

CCollection.cpp
#include "CCollection.h"
#include <algorithm>

CCollection::CCollection()
{
}

CCollection::~CCollection()
{
}

size_t CCollection::add(void *item)
{
	m_data.push_back(item);
	return (m_data.size() - 1);
}

void CCollection::insert(size_t position, void *item)
{
	m_data.insert((m_data.begin() + position), item);
}

void CCollection::remove(size_t index)
{
	m_data.erase(m_data.begin() + index);
}

void CCollection::remove(void *value)
{
	std::remove(m_data.begin(), m_data.end(), value);
}

void CCollection::clear(void)
{
	m_data.clear();
}

size_t CCollection::count(void)
{
	return m_data.size();
}

void * CCollection::at(size_t index)
{
	return m_data.at(index);
}

void CCollection::set(size_t index, void* value)
{
	m_data.assign(index, value);
}

Sample use case:
#include "CCollection.h"

int main()
{
  CCollection _one;

  std::string* hello1 = new std::string("Hello World 1");
  std::string* hello2 = new std::string("Hello World 2");
  std::string* hello3 = new std::string("Hello World 3");

  _one.add(hello1);
  _one.add(hello2);
  _one.add(hello3);

  _one.remove(0); // works, "Hello World 1" is removed, count is now 2 objects
  _one.remove(hello2); // does not work, it is still there and count is still 2

  (std::string*)_one.at(0); // references hello2 still;

  delete hello1;
  delete hello2;
  delete hello3;

  return 0;
}

The remove(void *item) does not work for me. I think I'm a bit confused as to pointer and extra inderection that is necessary. This is a base collection class that will then be used to create specific collection types by inheritance. I don't want to use templates because of the problem with sticking it in DLL and then dllimport/dllexport issues that are caused. This should work like .net 1.1 collections before 2.0 introduced generics. I'm planning to store pointers to objects in these collections. Can anyone look it over and give feedback as to why remove(void* item) would not work and any other advise? Thank you!

Share this post


Link to post
Share on other sites
fastcall22    10840
ref:
Quote:

[std::remove] Returns:
A forward iterator addressing the new end position of the modified range, one past the final element of the remnant sequence free of the specified value.


I believe you want to m_data.erase( std::remove( m_data.begin(), m_data.end(), value), m_data.end() );

Share this post


Link to post
Share on other sites
ChaosEngine    5185
I think this is a bad idea, frankly. First up, I see no gain with the base class, all you've done is remove type safety from your collection. You're still gonna have to implement almost all the functions again for each collection type. Plus, you're hiding the collection type. This is an important piece of information. I need to know if it's a vector (random access is fast, inserting in the middle is costly) or a list(no random access, inserting is quick).

There's a good reason the .net1.1 collections are almost never used now. Your reasoning for doing this, (dll issues) may not be as bad as you think. As long as both dll and client are compiled using the same compiler, you should be fine. If you can't guarentee this, I'd stick to passing arrays across the dll boundary.

Share this post


Link to post
Share on other sites
azherdev    112
I have a need for this type of API, I am not saying this is better than stl directly.

Problem I have with templates is that I can not seperate declaration and implementation into seperate files. Everything has to exist in the header file. I am using VC 2008 Pro and have found on the web no solution to the errors during compile time.

Anyways, I have actually switched to using std::list for now. Once I use this code inside my product, I can change the underlining container as I see fit. The only change that inherited classes will need to implement is the:

add
at ( 1 of 2 overloads )
insert
remove ( 1 of 2 overloads )

functions. Other, rather easy ones I admit, will stay the same. Now, if I see that speed and memory becomes an issue because of inheritance, I might take away the inheritance, but all the code using will not be affected. Right now, I need the API to be flushed out and logic to work, later I will revisit optimization.

AQTime is a god's gift for me in terms of profiling speed, converage, and hit count.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this