Sign in to follow this  
Ratslayer

C++ template restriction issues.

Recommended Posts

Ratslayer    110
Hello, I'm trying to use templates in C++ a la Java, where you can restrict generics parameters to ones that inherit a specific class. However, I couldn't find any way for C++ to restrict to/ensure that the types I pass to the template are inheriting a specific class (in my case it's BBComponent, which contains only a string Name). So I decided to just plug in an hope for the best which, obviously, didn't work out. Here's the code:

BBVector.h

#pragma once
#include "BBExternals.h"
template<class T>
class BBVector : public std::vector<T>
{
public:
BBVector(void){};
~BBVector(void){};

T GetByName(string name)
{
for(unsigned int i=0;i<size();i++)
if(get(i).Name==name)
return get(i);
throw(name);
};
int GetIdByName(string name)
{
for(unsigned int i=0;i<size();i++)
if(get(i).Name==name)
return i;
return -1;
}
bool remove(string name)
{
int n=GetIdByName(name);
if(n>=0)
erase(n);
else return false;
return true;
}
};


And here is are the errors it gives me:

1>c:\users\ratslayer\documents\visual studio 2010\projects\bbeditorconsole\bbeditorconsole\bbvector.h(13): error C2228: left of '.Name' must have class/struct/union
1> type is ''unknown-type''
1> c:\users\ratslayer\documents\visual studio 2010\projects\bbeditorconsole\bbeditorconsole\bbvector.h(11) : while compiling class template member function 'Team BBVector<T>::GetByName(string)'
1> with
1> [
1> T=Team
1> ]
1> c:\users\ratslayer\documents\visual studio 2010\projects\bbeditorconsole\bbeditorconsole\resourceman.h(10) : see reference to class template instantiation 'BBVector<T>' being compiled
1> with
1> [
1> T=Team
1> ]
1>c:\users\ratslayer\documents\visual studio 2010\projects\bbeditorconsole\bbeditorconsole\bbvector.h(13): error C3861: 'get': identifier not found
1>c:\users\ratslayer\documents\visual studio 2010\projects\bbeditorconsole\bbeditorconsole\bbvector.h(14): error C3861: 'get': identifier not found



As far as I can tell, it complains because T is not an actual class type and, therefor, it can not have instances and can not have attributes (thus T.Name does not have any meaning). However, it just told me that T=Team, so the compiler knows what T is and could easily convert the type and plug in .Name. What am I doing wrong? Or is there a different way to do this? I'm trying to make a class that inherits std::vector that will hold only instances of classes inheriting BBComponent, so I can implement removeByName, GetByName and GetIdByName functions.

Share this post


Link to post
Share on other sites
pablo24    156
Don't inherit from std::vector, it doesn't have a virtual destructor!

How about something like this?


#pragma once

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <stdexcept>
#include "BBExternals.h"

template<class T>
class BBVector
{
BOOST_STATIC_ASSERT((boost::is_base_of<BBComponent, T>::value));

typedef std::vector<T> conainer;
container values;

public:
const T& GetByName(string name) const
{
for(container::const_iterator iter = values.begin(); iter != values.end(); ++iter)
{
if(values[i].Name == name)
{
return values[i];
}
}
throw(std::runtime_error("Could no find element by name: " + name));
}

int GetIdByName(string name) const
{
for(container::const_iterator iter = values.begin(); iter != values.end(); ++iter)
{
if(values[i].Name == name)
{
return i;
}
}
return -1;
}

bool remove(string name)
{
int n = GetIdByName(name);
if(n >= 0)
{
values.erase(n);
return true;
}
return false;
}
};





I still think you should just use a boost::unordered_map<std::string, BBComponent>, because your container is slower (linear search) and goes completely against the standard container design.

Oh and did you intend to store polymorphic types in this container? Then use boost::ptr_unordered_map<std::string, BBComponent>.

Share this post


Link to post
Share on other sites
Ratslayer    110
Thank you for your help.

@kloffy The get is most likely an inherited function from one of vector's parent classes. I think I accidentally remembered the get from Java and wrote it, and VS2010 IntelliSense agreed with me. When I changed to at() everything works now.

@pablo24 This is a programming assignment, and I don't think I'm comfortable enough with boost to actually integrate it on-fly. I'll look into boost::unordered_map however once I'm done, thanks for the suggestion.

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