У меня есть этот класс:
class Mail {
public:
Mail(const string & msg) : msg(msg) {}
const string msg;
};
И эта структура, которая сравнивает два объекта Mail:
struct Compare {
bool operator()(const Mail & mail, Mail const & mail2) const {
return mail.msg < mail2.msg;
}
};
Я хочу иметь вектор с объектами Mail, отсортированными по их сообщению const string msg
. Однако, когда я пытаюсь вставить новый объект в вектор, используя lower_bound
, я получаю много ошибок, в том числе:
passing ‘const string as ‘this’ argument discards qualifiers.
int main() {
vector <Mail> mails;
Mail mail2("1");
mails.push_back(mail2);
const string msg = "2";
Mail mail(msg);
auto low = lower_bound(mails.begin(), mails.end(), mail, Compare());
// mails.push_back(mail); // OK
mails.insert(low, mail); // passing ‘const string as ‘this’ argument discards qualifiers
return 0;
}
Я еще не очень понимаю const
использование и не могу понять, что const
неправильно.
Извините, если этот вопрос уже задавался, но я пока не нашел ответа на эту проблему.
Спасибо за все ответы, теперь я понимаю проблему. Однако я не могу изменить class Mail
в том числе const string msg
. Я изменил вектор на вектор указателей vector<CMail*>
.
Проблемы здесь связаны с удаленным оператором присваивания копирования и удаленным оператором присваивания перемещения из-за члена const string msg;
в классе Mail
:
Deleted implicitly-declared copy assignment operator
A defaulted copy assignment operator for class
T
is defined as deleted if any of the following is true:
T
has a non-static data member of non-class type (or array thereof) that isconst
;Deleted implicitly-declared move assignment operator
The implicitly-declared or defaulted move assignment operator for class
T
is defined as deleted if any of the following is true:
- T has a non-static data member that is
const
;
Ошибки в C++ иногда трудно диагностировать. Мой совет — всегда начинать сверху и решать это в первую очередь. В этом случае есть их длинный список, но все они на самом деле об одном и том же — оператор присваивания для Mail
не может быть сгенерирован.
Подумайте об этом так: компилятор помогает и пытается сгенерировать (и внутри lower_bound()
использовать) эту функцию:
Mail& operator=( const& Mail mail )
{
msg = mail.msg;
return *this;
}
Но это невозможно, потому что это назначение в теле недействительно из-за того, что msg
является const
. Вы также не можете написать это самостоятельно, поскольку вы также не можете присваивать значение переменной const
.
Обычно вам не нужно, чтобы переменные-члены были const
, потому что они становятся const
, если экземпляр класса сам по себе const
:
const auto mail1 = Mail{"1"};
auto mail2 = Mail{"2"};
mail1.msg = "3"; // FAIL! msg is const since mail1 is const
mail2.msg = "4"; // Ok! msg is not const
Если вам нужен член const
, вы не можете использовать операторы присваивания с классом. Это перерывы.
Удалите это const
и все работает:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class Mail {
public:
Mail(const string & msg) : msg(msg) {}
string msg; //////////////////////////////// Not const!
};
struct Compare {
bool operator()(const Mail & mail, Mail const & mail2) const {
return mail.msg < mail2.msg;
}
};
int main() {
vector <Mail> mails;
Mail mail2("1");
mails.push_back(mail2);
const string msg = "2";
Mail mail(msg);
auto low = lower_bound(mails.begin(), mails.end(), mail, Compare());
// mails.push_back(mail); // OK
mails.insert(low, mail); // OK!
return 0;
}
Смотрите, как он работает в прямом эфире Coliru.
Сноски:
Compare
:const auto low = lower_bound( begin(mails), end(mails), mail,
[]( const auto& mail1, const auto& mail2 )
{ return mail1.msg < mail2.msg; } );
vector::emplace_back()
для создания элементов на месте, избегая копирования. Следующие блоки делают то же самое по сути, но второй более эффективен:const auto mail = Mail{"2"};
mails.push_back( mail2 ); // Copies
mails.emplace_back("2"); // Creates it right in the vector
ты уверен, что хочешь
string msg
бытьconst
? Это означает, что его нельзя изменить после инициализации, и именно это мешает вам его вставить.