Чтобы округлить число до разрешения, наилучшим способом является следующий, который может работать с любым разрешением (0,01 для двух десятичных знаков или даже других шагов):
>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95
>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0
Объекты в std::set
сохраняются как const StudentT
. Поэтому, когда вы пытаетесь вызвать getId()
с объектом const
, компилятор обнаруживает проблему, в основном вы вызываете функцию не-const-члена в const-объекте, которая не разрешена, поскольку не-константные функции-члены не делают НИКАКИХ ОБЯЗАТЕЛЬНО не изменить объект; поэтому компилятор должен сделать предположение safe , что getId()
может попытаться изменить объект, но в то же время он также замечает, что объект является const; поэтому любая попытка изменить объект const должна быть ошибкой. Следовательно, компилятор генерирует сообщение об ошибке.
Решение прост: сделайте функции const такими как:
int getId() const {
return id;
}
string getName() const {
return name;
}
Это необходимо, потому что теперь вы можете вызывать getId()
и getName()
для объектов const как:
void f(const StudentT & s)
{
cout << s.getId(); //now okay, but error with your versions
cout << s.getName(); //now okay, but error with your versions
}
В качестве побочного элемента вы должны реализовать operator<
как:
inline bool operator< (const StudentT & s1, const StudentT & s2)
{
return s1.getId() < s2.getId();
}
. Параметры примечаний теперь const
.
На самом деле стандарт C ++ (т. е. C ++ 0x draft ) говорит (tnx to @Xeo & amp; @Ben Voigt для указания этого на меня):
23.2 .4 Ассоциативные контейнеры 5 Для set и multiset тип значения совпадает с типом ключа. Для карты и мультимапа он равен паре. Ключи в ассоциативном контейнере неизменяемы. 6 итератор ассоциативного контейнера относится к категории двунаправленного итератора. Для ассоциативных контейнеров, где тип значения совпадает с типом ключа, оба итератора и const_iterator являются постоянными итераторами. Не указано, является ли итератор и const_iterator одним и тем же типом.
blockquote>Итак, реализация Dinkumware VC ++ 2008 ошибочна.
Старый ответ:
Вы получили эту ошибку, потому что в некоторых реализациях std lib
set::iterator
совпадает сset::const_iterator
.Например, libstdc ++ (поставляется с g ++) имеет его (см. здесь для всего исходного кода):
typedef typename _Rep_type::const_iterator iterator; typedef typename _Rep_type::const_iterator const_iterator;
И в SGI docs указывает:
iterator Container Iterator used to iterate through a set. const_iterator Container Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.)
С другой стороны, VC ++ 2008 Express компилирует ваш код, не жалуясь, что вы вызываете методы non const на
set::iterator
s.
Функции членов, которые не изменяют экземпляр класса, должны быть объявлены как const
:
int getId() const {
return id;
}
string getName() const {
return name;
}
В любое время, когда вы видите «отбрасывает квалификаторы», речь идет о const
или volatile
.
Позвольте мне привести более подробный пример. Что касается ниже структуры:
struct Count{
uint32_t c;
Count(uint32_t i=0):c(i){}
uint32_t getCount(){
return c;
}
uint32_t add(const Count& count){
uint32_t total = c + count.getCount();
return total;
}
};
Как вы видите выше, IDE (CLion) даст подсказки Non-const function 'getCount' is called on the const object
. В методе add
count
объявлен как объект const, но метод getCount
не является методом const, поэтому count.getCount()
может изменять члены в count
.
Ошибка компиляции, как показано ниже (основное сообщение в моем компиляторе):
error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]
Чтобы решить эту проблему, вы можете:
uint32_t getCount(){...}
на uint32_t getCount() const {...}
. Таким образом, count.getCount()
не будет изменять элементы в count
. или
uint32_t add(const Count& count){...}
на uint32_t add(Count& count){...}
. Поэтому count
не заботится об изменении членов в нем. Что касается вас, объекты в std :: set сохраняются как const StudentT, но метод getId
и getName
не const, поэтому вы указываете вышеприведенную ошибку.
Вы также можете увидеть этот вопрос Значение 'const' последним в объявлении функции класса? для более подробно.