C++ – binding of reference to a value of type drops qualifiers

c

I have the following source from the Text Accelerated C++. When I attempt to compile the source file I get the following compilation error listed below. I'm a novice of the C++ language so your assistance would be appreciated.

#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>

using namespace std;

struct Student_info {
    string name;
    double midterm, final;
    vector<double> homework;
};

double median(vector<double>);
double grade(const Student_info&);
double grade(double, double, double);
double grade(double, double, const vector<double>&);
istream& read_hw(istream&, vector<double>&);
istream& read(istream&, Student_info&);
bool compare(const Student_info&, Student_info&);

int main() {

    vector<Student_info> students;
    Student_info record;
    string::size_type maxlen = 0;

    while(read(cin, record)) {
        maxlen = max(maxlen, record.name.size());
        students.push_back(record);
    }

    sort(students.begin(), students.end(), compare);

    for(vector<Student_info>::size_type i = 0;
            i != students.size(); ++i) {

        cout << students[i].name << string(maxlen + 1 - students[i].name.size(), ' ');

        try {
            double final_grade = grade(students[i]);
            streamsize prec = cout.precision();
            cout << setprecision(3) << final_grade
                    << setprecision(prec);
        } catch(domain_error& e) {
            cout << e.what();
        }
        cout << endl;
    }
    return 0;
}

double median(vector<double> vec) {
    typedef vector<double>::size_type vec_sz;
    vec_sz size = vec.size();

    if(size == 0)
        throw domain_error("median of an empty vector");

    sort(vec.begin(), vec.end());
    vec_sz mid = size/2;

    return size%2 == 0 ? (vec[mid] + vec[mid - 1])/2 : vec[mid];
}
double grade(const Student_info& s) {
    return grade(s.midterm, s.final, s.homework);
}
double grade(double midterm, double final, double homework) {
    return 0.2*midterm + 0.4*final + 0.4*homework;
}
double grade(double midterm, double final, const vector<double>& hw) {
    if(hw.size() == 0)
        throw domain_error("student has done no homework");
    return grade(midterm, final, median(hw));
}
istream& read_hw(istream& in, vector<double>& hw) {
    if(in) {
        hw.clear();

        double x;
        while(in >> x)
            hw.push_back(x);
        in.clear();
    }

    return in;
}
istream& read(istream& is, Student_info& s) {
    is >> s.name >> s.midterm >> s.final;
    read_hw(is, s.homework);
    return is;
}
bool compare(const Student_info& x, const Student_info& y) {
    return x.name < y.name;
}

binding of reference to type 'Student_info' to a value of type 'const Student_info' drops qualifiers compute_grades_rev-b
line 125, external location: /usr/include/c++/4.2.1/bits/stl_algo.h C/C++ Problem

Here is the code from stl_algo.h:

 template<typename _Tp, typename _Compare>
    inline const _Tp&
    __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp)
    {
      // concept requirements
      __glibcxx_function_requires(_BinaryFunctionConcept<_Compare,bool,_Tp,_Tp>)
      if (__comp(__a, __b))
    if (__comp(__b, __c))
      return __b;
    else if (__comp(__a, __c))
      return __c;
    else
      return __a;
      else if (__comp(__a, __c))
    return __a;
      else if (__comp(__b, __c))
    return __c;
      else
    return __b;
    }

I change the declaration of the compare function from:

bool compare(const Student_info&, Student_info&);
bool compare(const Student_info, Student_info);

Now it compiles.

Best Answer

The error is indicating that you cannot bind a non-const reference to a const-object, as that would drop (discard in other compiler's errors), disregard or ignore the const qualifier.

What it tries to indicate is that if the operation was allowed you would be able to modify the object through the reference ignoring the fact that the object itself is const, breaking const-correctness.

In your particular code, the function __median in the library takes __a, __b, and __c by const reference and tries to call the __comp function, which in your program (first declaration) takes the second argument by non-const reference. To be able to call __comp(__a,__b) (or any other call to __comp in that function) it would have to bind an object accessible only through a const& to the second argument that takes a non-const reference. This is most probably a typo, since you define compare below with both arguments being const references.

Change the declaration of compare before main to:

bool compare(const Student_info&, const Student_info&);
//                                ^^^^^