I am trying to overload the subscript operator -i know it as the element access operator- to take a char * or a std::string.
I have a struct
struct foo
{
int Age;
const char *Name;
};
and a std::vector that will be holding multiple instances of this struct.
std::vector<foo>bar;
my goal is to be able to access each foo in bar by calling them by their name.
std::cout<<"Simon's age is: "<<bar["simon"];
I've just been searching google for a long while trying to find an example or something to go off, with no luck.
i thought that this would work
foo operator[](char *Name)
{
for(int i=0;i<bar.size();i++)
{
if(bar[i].Name == Name){return bar[i];}
}
}
however apparently i'm doing something wrong
I do know this could be done with an std::map but i'd rather use an std::vector, thanks.
I would greatly appreciate your help however you choose to offer it. Thank you .
To do what you want requires inheriting from std::vector. Otherwise you can't overload its methods.
Something like the following (untested).
struct fooVector : public std::vector<foo> {
typedef std::vector<foo> super;
using super::size;
...
foo& operator[](char const* Name) {
super& self=*this;
for(int i=0;i<size();i++)
{
if( ! strcmp( self[i].Name, Name) ){return self[i];}
}
// Need to do something reasonable if not found
}
};
bar[i].Name == Name
was probably meant to be
strcmp(bar[i].Name, Name) == 0
However, you'll be better off using std::string
s than managing plain char pointers.
And instead of inheriting form a vector, create a class with a vector as a member and have your operator[]
on that class.
First of all there are some problems with your test:
1) you're using const char* for string type, comparing with == would likely fail as you're comparing two pointers and not their content. you need to use strcmp or better use std::string (c++ way)
2) what if your index operator would not find the value you're looking for?
I don't think this is a proper way of doing this but in case you really want to use vector you can inherit your own class and define new operator which uses const char* as a index argument:
#include <vector>
#include <iostream>
#include <string.h>
struct foo {
int age;
const char *name;
};
class MyVector : public std::vector<foo> {
public:
const foo* operator[](const char* name) const {
for (auto it=cbegin(); it != cend(); ++it) {
if (strcmp(it->name, name) == 0) {
return &(*it);
}
}
return nullptr;
}
};
int main(int argc, char *argv[]) {
foo foo1 = { 10, "abc" };
foo foo2 = { 20, "test" };
MyVector v;
v.push_back(foo1);
v.push_back(foo2);
std::cout << "test: " << v["test"]->age << std::endl;
}
Although it's not generally advised to inherit from stl containers (they don't have virtual destructors), if you don't add any data attributes to inherited class you should be fine.
But I would suggest you to consider using std::map as a container and std::string as index / name attribute type. Searching vector has linear complexity but std::map has logaritmic complexity. Or you can consider using hash tables.