Why do I get this error "expression must be an lvalue or a function designator" for some of my data members?

I am trying to create a function that prints whatever I feed it from the class I created. I can only get some of my class object data members to work with my print function.

I have tried using pointers and references in some source codes I found online but they didn't work. After working on this problem for about a week now I feel like I have tried everything.

void print(string* object);


enum Degree { SECURITY = 1, NETWORKING = 2, SOFTWARE = 3};
class Student {
    public:
        Student(string ID, string first, string last, string Email, int Age, int days1, int days2, int days3, Degree StudentDegree) {
            studentID = ID;
            firstName = first;
            lastName = last;
            email = Email;
            age = Age;
            daysTillComplete[0] = { days1 };
            daysTillComplete[1] = { days2 };
            daysTillComplete[2] = { days3 };
            studentDegree = StudentDegree;
            return;
        }

        string getID() const;
        void setID(string ID);

        string getFirst() const;
        void setFirst(string ID);

        string getLast() const;
        void setLast(string ID);

        string getEmail() const;
        void setEmail(string ID);

        int getAge() const;
        void setAge( int Age);

        int getdays1();
        int getdays2();
        int getdays3();
        void setDaysTilComplete(int days, int days1, int days2);

        Degree getDegree() const;
        void setDegree(Degree degreeType);

    private:
        string studentID = "No name"; 
        string firstName = "No name";
        string lastName = "No name";
        string email = "No name";
        int age = 7;
        int daysTillComplete[3];
        Degree studentDegree = NETWORKING;
};

void print(string* object) {
    cout << *object << endl;
}
string Student::getID() const {
    return studentID;
}
string Student::getFirst() const {
    return firstName;
}
string Student::getLast() const {
    return lastName;
}
string Student::getEmail() const {
    return email;
}
int Student::getAge() const {
    return age;
}
int Student::getdays1() {
    return daysTillComplete[0];
}
int Student::getdays2() {
    return daysTillComplete[1];
}
int Student::getdays3() {
    return daysTillComplete[2];
}
Degree Student::getDegree() const {
    return studentDegree;
}
void Student::setID(string ID) {
    studentID = ID;
}
void Student::setFirst(string first) {
    firstName = first;
}
void Student::setLast(string last) {
    lastName = last;
}
void Student::setEmail(string Email) {
    email = Email;
}
void Student::setAge(int studentAge) {
    age = studentAge;
}
void Student::setDaysTilComplete(int days1, int days2, int days3) {
    daysTillComplete[0] = days1;
    daysTillComplete[1] = days2;
    daysTillComplete[2] = days3;
}
void Student::setDegree(Degree degreeType) {
    studentDegree = degreeType;
}

int main() {
    Student vallery("A1", "Vallery", "Williams", "vallery.a.williams1234@gmail.com",21,52,28,32,NETWORKING);    
    print(&vallery.getID());
    print(&vallery.getFirst());
    print(&vallery.getLast());
    print(&vallery.getEmail());

    //print(&vallery.getAge());     <--- will not compile if this statement is in the program
    //print(&vallery.getdays1());       <--- will not compile if this statement is in the program
    ////print(&vallery.getdays2());     <--- will not compile if this statement is in the program
    ////print(&vallery.getdays3());     <--- will not compile if this statement is in the program
    //print(&vallery.getDegree());      <--- will not compile if this statement is in the program

    cin.get();


    return 0;
}

My expected results for example print(vallery.getFirst); would be print vallery. That works, but when I do print(vallery.getAge); it should be 21 but I can't even compile it because I get the "expression must be an l-value or function designator" error. Also using int instead of string for the data type of the print function doesn't work either. I must be using something incorrectly. Can someone point me in the right direction? After a bunch of research I haven't found any solutions.

2 answers

  • answered 2019-05-15 03:26 Bar Stool

    There are several things are are probably going wrong with this code.

    The most obvious is that your print function expects a string*. The calls that fail are those where you try and give the function something that is not a string*. For example, getAge() returns a int, where you are taking the address of the returned int. So you are trying to call print(int*) which then is failing. To solve this you can either using templating or have overloads. Here is a recommended template function:

    template <typename T>
    print (const T& _object) 
    {
     cout << _object << endl;
    }
    

    A second problem, which is what is masking this first error comes from the fact you are taking a ptr instead of a reference (or a const reference as in my template function). If you want to print something, you want it to definitely be there and not a nullptr. So use references. In saying this, I think the ones that you say will work, definitely shouldn't work (even though they are string*'s) under any sane compiler. Perhaps the current error is hiding those errors.

    The error “expression must be an lvalue or a function designator” comes from the fact that you are trying to take the address of an r-value. That is a value that is temporary and/or has not been bound to a name. Your getters return a copy of the value stored in your student object and this value has no address. You are trying to get the address of an addressless value, hence the error that it must be lvalue.

    To solve this: Firstly don't use pointers, use a const reference. Secondly, have your getters return a const reference for objects. For example,

    const string& Student::getID() const;
    

    If your print function takes a const reference, it is able to handle a temporary variables for the cases where you return an int or other primitive type. Since your other getters return a reference to an addressable value, the print function can also take this reference without having to needlessly copy the values.

  • answered 2019-05-15 03:46 arundeep chohan

    void print(string* object);
    //You need a string for this.
    
    print(&vallery.getID());     //will work
    print(&vallery.getFirst());     //will work
    print(&vallery.getLast());     //will work
    print(&vallery.getEmail());     //will work
    
    string Student::getID() const {
    return studentID;
    }
    string Student::getFirst() const {
    return firstName;
    }
    string Student::getLast() const {
     return lastName;
    }
     string Student::getEmail() const {
    return email;
    }
    
    //All of these are ints:
    
    print(&vallery.getAge());     //won't work
    print(&vallery.getdays1());     //won't work
    print(&vallery.getdays2());     //won't work
    print(&vallery.getdays3());     //won't work
    print(&vallery.getDegree());     //won't work
    
    int Student::getAge() const {
    return age;
    }
    int Student::getdays1() {
    return daysTillComplete[0];
    }
    int Student::getdays2() {
    return daysTillComplete[1];
    }
    int Student::getdays3() {
    return daysTillComplete[2];
    }
    
    
    //This one is a class Degree:
    
    Degree Student::getDegree() const {
    return studentDegree;
    }