Call to implicitly-deleted copy constructor...

I think that i'm missing something. Compiler returns me this error:

Call to implicitly deleted copy constructor of 'std::__1::unique_ptr<Account, std::__1::default_delete<Account> >'

When i define method "void addNews(const News& news);" in Social class..

But Account class what matter? O.o


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
#ifndef Social_hpp
#define Social_hpp

#include "User.hpp"
#include "Company.hpp"
#include "News.hpp"
#include "Group.hpp"

class Social{
    
private:
    
    vector<unique_ptr<Account>> vec;
    vector<News> news;
    int nElement = 0;
    
    
public:
    //Constructors
    Social();
    
    //Methods
    void addAccount(unique_ptr<Account> account);
    void addNews(const News& news);
    string removeElement(const string &username);
    void nUserByData(const string& date);
    int nOfElement() const;
    void nAccountPerType();
    int checkType(vector<unique_ptr<Account>>::iterator it) const;
    void companyInfo();
    void mostEmployee();
    //void mostLikedNews();
    
    
    
};

#endif /* Social_hpp */ 


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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

#include "Social.hpp"
#include "User.hpp"

//Constructors
Social::Social(){
    
}


//Methods



void Social::addAccount(unique_ptr<Account> account){
    vec.push_back(move(account));
    nElement++;
}

void Social::addNews(const News& news){
    this->news.push_back(news);
}

string Social::removeElement(const string &username){
    int i = 0;
    for(vector<unique_ptr<Account>>::iterator it = vec.begin(); it!=vec.end(); it++, i++){
        cout<<(*it)->getUsername()<<endl;
        if((*it)->getUsername() == username){
            vec.erase(vec.begin()+i);
            nElement--;
            return "Eliminato con successo\n";
        }
    }
    return "Non è stato trovato l'elemento\n";
}

void Social::nUserByData(const string &date){
    int i = 0;
    for(vector<unique_ptr<Account>>::iterator it = vec.begin(); it!=vec.end(); it++){
        if(auto d = dynamic_cast<User*>(it->get())){
            if(d->getDate() > date){
                i++;
            }
        }
    }
    if(i == 0){
        cout<<"Non ci sono utenti nati dopo quella data"<<endl;
    }else{
        cout<<"Il numero di utenti nati dopo quella data è: "<<i<<endl;
    }
}

int Social::nOfElement() const{
    return nElement;
}


int Social::checkType(vector<unique_ptr<Account>>::iterator it) const{
    if(auto d = dynamic_cast<User*>(it->get())) {
        return 1;
    }
    else if(auto d = dynamic_cast<Company*>(it->get())){
        return 2;
        
    }else{
        return 3;
    }
}


void Social::nAccountPerType(){
    int u=0,c=0,g=0;
    for(vector<unique_ptr<Account>>::iterator it = vec.begin(); it!=vec.end(); it++){
        switch(checkType(it)){
            case 1:
                u++;
                break;
            case 2:
                c++;
                break;
            case 3:
                g++;
                break;
        }
    }
    cout<<"Numeri totali di account: "<<nElement<<"\nNumero di account di tipo User: "<<u<<"\nNumero di account di tipo Company: "<<c<<"\nNumero di account di tipo Group: "<<g<<endl<<endl;
}

void Social::companyInfo(){
    for(vector<unique_ptr<Account>>::iterator it = vec.begin(); it!=vec.end(); it++){
        if(auto d = dynamic_cast<Company*>(it->get())){
            cout<<"L'azienda: "<<d->getName()<<"\nHa un numero di dipendenti pari a: "<<d->nLink("Employee")<<"\nEd un numero di consociate pari a "<<d->nLink("Company")<<endl;
        }
    }
}

void Social::mostEmployee(){
    int i = 0, max = 0, j = 0;
    for(vector<unique_ptr<Account>>::iterator it = vec.begin(); it!=vec.end(); it++, i++){
        if(auto d = dynamic_cast<Company*>(it->get())){
            if(max < d->nLink("Employee")){
                max = d->nLink("Employee");
                j = i;
            }
        }
    }
    if(max == 0){
        cout<<"Nessun'azienda possiede dipendenti";
    }else{
        cout<<"L'azienda con il maggior numero di dipendenti è: "<<vec[j]->getName()<<"\nCon un numero di dipendenti pari a: "<<max<<endl;
    }
}

/*void Social::mostLikedNews(){
    int max = 0, j =0, i = 0;
    for(vector<News>::iterator it = news.begin(); it!=news.end(); it++, i++){
        if(it->getNlike() > max){
            max = it->getNlike();
            j = i;
        }
    }
    if(max == 0){
        cout<<"Non ci sono notizie";
    }else{
        cout<<"La notizia più apprezzata è quella di: "<<this->news[j].getID()->getName()<<"\nCon un numero di apprezzamenti pari a: "<<max<<endl;
    }
}*/



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

#ifndef News_hpp
#define News_hpp

#include <stdio.h>
#include <string>
#include "Account.hpp"

class News{
    
private:
    Account* id;
    string text;
    string date;
    vector<unique_ptr<Account>> like;
    vector<unique_ptr<Account>> dislike;
    
public:
    
    News();
    News(Account& id, const string& text, const string& date);
    int getNlike() const;
    int getDislike() const;
    Account* getID() const;
    
};

#endif /* News_hpp */




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

#include "News.hpp"


News::News(){
    
}


News::News(Account& id, const string& text, const string& date){
    this->id = &id;
    this->text = text;
    this->date = date;
}

int News::getNlike() const{
    return like.size();
}

int News::getDislike() const{
    return dislike.size();
}

Account* News::getID() const{
    return id;
}


Last edited on
What is this Account? We see no definition anywhere.
Account is the base class of other 3 classes.. i'll past here just hpp

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

#ifndef Account_hpp
#define Account_hpp

#include <stdio.h>
#include <string>
#include <iostream>
#include <vector>


using namespace std;

class Account{
    
protected:
    string username;
    string name;
    
public:

    //Constructors
    Account(){
        username = "Account";
        name = "";
    }
    
    //Virtual Members
    
    /*
     Metodo virtuale, ritorna l'identificativo dell'Account
     @return: string
     */
    virtual string getUsername() const{
        return this->username;
    }
    
    /*
     Metodo virtuale, ritorna il nome dell'Account
     @return: string
     */
    virtual string getName() const{
        return this->name;
    }
    
    /*
     Metodo virtuale, stampa le specifiche dell'Account
     @return: void
     */
    virtual void printInfo() const{
        cout<<"Simple Account"<<endl<<endl;
    }
    
    /*
     Metodo virtuale, ritorna il tipo di Account
     @return: int
     */
    virtual int getType() const{
        return 0;
    }
    
    /*
     Metodo virtuale
     @return: void
     */
    virtual void setUsername(const string& username){
        this->username = username;
    }
    
    /*
     Metodo virtuale
     @return: void
     */
    virtual void setName(const string& name){
        this->name = name;
    }
};

#endif /* Account_hpp */



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
61
62
63
64
65
66
#ifndef User_hpp
#define User_hpp

#include "Account.hpp"
#include "Link.hpp"


class User : public Account{
    
private:
    
    //string username; INHERITED
    //string name;     INHERITED
    
    string date;
    string surname;
    string address;
    vector<Link> links;

public:
    
    //CONSTRUCTORS
    User();
    User(const string &username, const string &name, const string &surname, const string &address, const string &date);
    
    //GETTERS
    string getSurname() const;
    string getDate() const;
    string getAddress() const;
    /*
     virtual string getUsername() const{
        return this->username;
     }
     
     virtual string getName() const{
        return this->name;
     }
     */

    
    //SETTERS
    void setSurname(const string &surname);
    void setDate(const string &date);
    void setAddress(const string &address);
    /*
    virtual void setUsername(const string& username){
        this->username = username;
    }

    virtual void setName(const string& name){
        this->name = name;
    }
    */
    
    
    //Methods
    void addLink(const Link &link);
    void printAllLinks();
    void printInfo() const override;
    int getType() const override;
    
    
    
};

#endif /* User_hpp */ 


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
#ifndef Company_hpp
#define Company_hpp

#include "Account.hpp"
#include "Link.hpp"


#endif /* Company_hpp */

class Company : public Account{
    
private:
    //string username; Inherited
    //string name;     Inherited
    
    string creationData;
    string operativeHq;
    string address;
    string productType;
    vector<Link> links;
    
public:
    //Constructors
    Company();
    Company(const string &username, const string &name, string creationData, const string &operativeHq, const string &address, const string &productType);
    
    //Getters
    string getCreationData() const;
    string getOperaiveHq() const;
    string getAddress() const;
    string getProductType() const;
    
    //Setters
    void setCreationData(const string &creationData);
    void setOperativeHq(const string &operativeHq);
    void setAddress(const string &address);
    void setProductType(const string &productType);
    
    //Methods
    void addEmployee(const Link &link);
    void printInfo() const override;
    int getType() const override;
    int nLink(const string& linkType);

    
    /* INHERITED
     virtual string getUsername() const{
     return this->username;
     }
     
     virtual string getName() const{
     return this->name;
     }
     */
};
Hi,
news has a

vector<unique_ptr<Account>> like;

So do you need to std::move that, in the addNews function?

Some other ideas:

There are a few places where you could use a range based for loop instead of iterators.

It's better not to have protected data, that's nearly as bad as public data.

One doesn't have to have the const in function declaration parameters, but do put it in the definition.

You should qualify all the std things with std:: Ideally put your own code into it's own namespace.
I didn't understand what do you mean with:

news has a

vector<unique_ptr<Account>> like;

So do you need to std::move that, in the addNews function?

Why protected data is bad as public data?.. encapsulation does not make sense then..

I studied that const in parameters means that u will not modify that parameter, so compiler doesn't allocate other space (something like that).

std:: is so uncomfortable using namespace std has been created for that.. or not? xD

Please i have to pass an exam and i don't like c++.. xD it's not easy like java.. I'm having a lot of problems with c++
Last edited on
Hi,

The class news has the vector<unique_ptr<Account>> like;, so you can't push_back like you do here:

1
2
3
void Social::addNews(const News& news){
    this->news.push_back(news);
}


So I was saying you need to move it instead.

Why protected data is bad as public data?.. encapsulation does not make sense then..


Encapsulation works with private data. The main reason protected data is bad is that it's not a function, which means that it's easy to break code if the representation of the data changes.

I studied that const in parameters means that u will not modify that parameter, so compiler doesn't allocate other space (something like that).


The const is fine, I am saying is not necessary to have it in the declaration, but do have it in the definition:

User(const string &username, const string &name, const string &surname, const string &address, const string &date);


User::User(const string &username, const string &name, const string &surname, const string &address, const string &date);

The reason for this is that a user of the code, seeing the header file only, might think they have to make to make an argument const, which isn't necessary. Don't worry I too did that for ages before I found out.

std:: is so uncomfortable using namespace std has been created for that.. or not? xD


That is a very common misconception for people new to C++. The main problem is clashes with function and variable names - which namespaces are supposed prevent ! :+) that using statement subverts that. There is loads of info on the internet about that very thing. That's why I also mentioned putting your code in it's own namespace.

It's tough coming from another OOP language like Java, which could be seen as been kind of similar to C++, but not really. Hopefully you can add the things I mentioned and get some extra points for your assignment.
Last edited on
Thank you man, for the tips!! xD

I understand all!! but i just don't understand why i cant push back.. i'm pushing a "News" object into vector<News>.. what about attribute of News?... vector<unique_ptr<Account>> like; is an attribute, i really don't understand why that doesn't allow me to push back..
Last edited on
i really don't understand why that doesn't allow me to push back..


push_back implies a copy of the whole object, which one cannot do with a unique_ptr

With std:: , you will get used to it ...... and that is what all the experienced C++ coders do :+)

You might also need move constructors, see rule of 5:

https://en.cppreference.com/w/cpp/language/rule_of_three

Good Luck !!
The std::unique_ptr follows the There can be only one! principle.

1
2
3
int foo = 42;
std::vector<int> bar;
bar.push_back( foo ); // bar gets a copy of foo 

Your News has (multiple) unique_ptr. You (attempt to) create a copy of news object.
Therefore, you must create a copy of the member unique_ptr.

By definition, each unique_ptr is unique. No copies allowed.

You can transfer ownership from one unique_ptr to an another, but you cannot make a copy.

The const is fine, I am saying is not necessary to have it in the declaration, but do have it in the definition:

1
2
3
4
User(string &username,  string &name,  string &surname,  string &address,  string &date);


User::User(const string &username, const string &name, const string &surname, const string &address, const string &date);


What? Both the definition and the implementation must agree on the number and types of parameters. The const qualifier modifies the type so const "type" is not the same as "type".

jlb wrote:
What? Both the definition and the implementation must agree on the number and types of parameters. The const qualifier modifies the type so const "type" is not the same as "type".


Hi,

I learnt this from JLBorges awhile back, it is right - try it :+)

The other thing about it is the function receives copies of the arguments, it is those which the const is applied. It still works for references. There is probably something in the standard about it, I will see if I can find it.

A couple of other pedantic style type things for the OP , vittorioc98

I place the reference or pointer next to the type (not next to the variable identifier), because C++ is all about types. Also, if there are multiple parameters, I put them each of them on it's own line - it's easier to read IMO, and one could put comments there:

1
2
3
4
5
6
User(std::string& username,  
         std::string& name, 
         std::string& surname,  
         std::string& address,  
         std::string& date
        );


I do the same in the function definition :+)
It doesn't work in that case: those two forms of User::User declare different functions.
http://coliru.stacked-crooked.com/a/5b8d7705e282a866

When a function is declared, the parameters undergo some transformations. Parameters with function types are converted to the corresponding pointer-to-function type, arrays are converted to pointers, and top-level cv-qualifiers are dropped.
See:
https://en.cppreference.com/w/cpp/language/function#Parameter_list

In other words, the declarations void f(int); and void f(int volatile const); declare the same function; those cv-qualifications are dropped. But void f(int &) and void f(int const&) do not, because the const in the latter is not at the "top-level".

See this S/O answer, for example, about top-level qualifications: https://stackoverflow.com/a/24676976/2085046
Or the standards quote that the answer predates or misses:
[basic.type.qualifier]
In this document, the notation cv (or cv1, cv2, etc.), used in the description of types, represents an arbitrary set of cv-qualifiers, i.e., one of {const}, {volatile}, {const, volatile}, or the empty set. For a type cv T, the top-level cv-qualifiers of that type are those denoted by cv. [ Example: The type corresponding to the type-id const int& has no top-level cv-qualifiers. The type corresponding to the type-id volatile int * const has the top-level cv-qualifier const. For a class type C, the type corresponding to the type-id void (C​::​* volatile)(int) const has the top-level cv-qualifier volatile. — end example ]

http://eel.is/c++draft/basic.type.qualifier#5

For reference types, the rules apply to the subtle distinction between reference-to-const and const reference to const (i.e., where the reference - the alias itself - is const). If one manages to write the latter form, we can see that the rules still apply, even to references.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void g(int const&); 
// const is not at the top-level, and is not stripped.
void g(int &) {}; // declares a different function

using my_type = int const&; // reference to const int
void f(my_type);
void f(my_type const) {} // declares the same function; 
// const in the parameter is at the top level, and is ignored

int main()
{
    g(2); // linker error: g(int const&) is declared and not defined
    f(2);  // okay
}

http://coliru.stacked-crooked.com/a/cf7c4b922415864c
Last edited on
@vittorioc98

My apologies, I was discombobulated (wrong / confused) on that point. It works for pass by value.

Sorry to mislead you on that point.

There is a whole topic about move semantics, but I guess your code is fine as it is now :+)
Topic archived. No new replies allowed.