Using container modifiers with containers declared with custom classes?

I'm... thinking no, but what do I know. I created a vector using a custom class that has it's own public and private data/ members. I wanted to use push_back() with my custom class to add element so I don't have to number the elements MyVect[0], MyVect[1], etc.

I thought I would create a custom iterator using end() so I could maybe MyVect[MyIt], MyVect[MyIt], or something like that, but before trying that I'd like to know if push_back() is available to me with what I'm doing. Code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class UserData{

	private:

		string Name;
		string Pass;
		string Access;

	public:

		void AddUser(string, string, string);
		string GetName();
		string GetPass();
		string GetAccess();

};

vector <UserData> Users;

void SetUserData(UserData &Users){

	//Users[0].AddUser("c", "c", "Creator");
	//Users[1].AddUser("j","a","Admin");
	//Users[2].AddUser("d","u","User");
	return;

}

void UserData::AddUser(string N, string P, string A){

	Name = N;
	Pass = P;
	Access = A;
	return;

} //END AddUser

string UserData::GetName(){

	return Name;

}

string UserData::GetPass(){

	return Pass;

}

string UserData::GetAccess(){

	return Access;

}
Last edited on
standard vector is rather resilient. You can usually make a vector of your home rolled classes. It will want a default public constructor and an assignment operator, and possibly one or two other such things (copy ctor sometimes?) (I forget which ones it needs for the basic act of making the vector and which ones crop up if you do other operations). Its a little muddled for me because it generates what it needs sometimes and for more complex objects it will not, but most of my stuff I keep on the simple side.

It does not require an iterator in the class. Other things may, but just poking it into a vector will not.
Push back itself will require that assignment or copy ctor, whatever it does internally.
Last edited on
Ugh, definitely dont want to create my own vector the way you mentioned.

I know the class itself doesnt require an iterator, but for the vector itself i does. When i have the time in going to try it and see what happens. I need to add a class element to the end of the vector everytime something is added. If i remove one of those added class elements, i wont have holes in the vector. Everything is always added in sequential order. In my code you can se my commented code where i was adding stuff manually via index numbers. Dont want that.
you misread what I said.
std vector will let you make a vector of your own classes if you add a couple of things to them that it may need. The things you need to add are often trivial.

if you can make std vector happy, it will let you push back all day long.
There is emplace_back, for which one would need a constructor. I wouldn't have the AddUser function, make the ctor instead.

Consider the following:

Rename UserData to User and make it a struct instead of a class;
Have a class named UserData with a private std::vector<User> ;
Implement functions that populate (emplace_back) and retrieve data to/from the UserData vector;

User could be a plain struct instead of a class because it has no invariants. It is OK because the collection of User is in a private variable in UserData.

With functions:
 
void AddUser(string, string, string);


Provide identifiers (names) for the parameters. One needs a way of referring to each argument, you do this in the implementation, but in my mind knowing that a function takes 3 strings is insufficient for readability.

Make the parameters const references, put the & next to the type - this is the constructor:

1
2
3
4
5
6
7
8
 User(const string& NameArg,
          const string& PassArg,
          const string& AccessArg)
          : // introduces initialiser list
          Name {NameArg},
          Pass {PassArg},
          Access {AccessArg}
{}


Notice the way I have formatted the code - easier to read IMO. Also that the order is the same as in the class/struct definition.

The Arg part of the identifier is a personal preference; I could have done this:
1
2
3
4
: // introduces initialiser list
          Name {Name},
          Pass {Pass},
          Access {Access}


Did you mention a need to erase items in the container? If so, a std::map may be better. However, note that performance will probably not be measurable in a toy program with a small amount of data, one usually needs millions of items to measure any change in performance.

Also note that std::vector is amazing performance wise compared to other containers. I once did an exercise comparing std::vector with std::map, vector was faster at creating & sorting, than map was at just creating. I had to put 8 million items into a map before it was quicker than vector. There is a bunch of technical reasons why this is so.

But std::map has advantages with insert and emplace and try_emplace in that it checks if there is already a member with that key, which I imagine is what one wants for a container or User names.
It's a good idea to have a data model that separates the object from a list of the same objects.
It's also a bit strange to have a method that hard codes the data. The norm woud be to initialise the vector/database via an array, another vector or similar and pass that to the set data method, but there again maybe that's what the parameter in @OP line 20 is supposed to do.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <string>
#include <iostream>
#include <vector>

using namespace std;

class User
{
private:
    string name;
    string pass;
    string access;

public:
    User();
    User( std::string aName, std::string aPass, std:: string aAccess)
    {
        name = aName;
        pass = aPass;
        access = aAccess;
    }

    string GetName(){return name;}
    string GetPass(){return pass;}
    string GetAccess(){return access;}
};

class UserData
{
private:
    vector<User> database;
public:
    void SetUserData(){

        this->AddUser( {"c", "c", "Creator"} );
        this->AddUser( {"j","a","Admin"} );
        this->AddUser( {"d","u","User"} );
        return;
    }

    void AddUser(User aUser){ database.push_back(aUser); }

    void display()
    {
        for(auto i: database)
        {
            cout <<
            i.GetName() << ' ' << i.GetPass() << ' ' << i.GetAccess() << '\n';
        }
    }
};

int main()
{
    UserData users;
    users.SetUserData();
    users.display();

    return 0;
}


c c Creator
j a Admin
d u User
Program ended with exit code: 0
Topic archived. No new replies allowed.