Мейерс рекомендует реализовывать неконстантную функцию посредством константной версии путем снятия константности со второй.
Вопрос: есть ли какие-либо гарантии стабильности (правильности?) работы следующего примера:
template <typename Var, TID>
class Container
{
private:
typedef std::map<TID, Var> Container_Type;
Container_Type vars;
public:
Var& Get(TID ID)
{
// можно ли?return const_cast<Var&>(static_cast<const Container&>(*this).Get(ID)); // call constant version of Get
}
const Var& Get(TID ID) const
{
Container_Type::const_iterator it = vars.find(ID);
assert(it != vars.end());
return it->second;
}
const Data_Type& operator[](TID ID) const { return Get(ID).Value; }
Data_Type& operator[](TID ID) { return Get(ID).Value; }
};
struct Var
{
int Value;
};
Container<int, Var> c;
Re: Вопрос по снятию константности c const_iterator
так и лучше и понятнее и надёжнее защита от изысков реализаций STL:
template <typename Var, TID>
class Container
{
private:
typedef std::map<TID, Var> Container_Type;
mutable Container_Type vars;
Var& doGet( TID ID ) const
{
Container_Type::iterator it = vars.find(ID);
assert(it != vars.end());
return it->second;
}
public:
Var& Get(TID ID)
{
return doGet( ID );
}
const Var& Get(TID ID) const
{
return doGet( ID );
}
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Вопрос по снятию константности c const_iterator
От:
Аноним
Дата:
23.01.08 13:09
Оценка:
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Аноним, Вы писали:
B>Вообще это достаточно распространенный прием. На основании чего возникли сомнения?
уже опередили меня.
т.е. опасения связаны с тем, что, как мне кажется, в стандарте не описано, что const версии должны реализовываться аналогично не const, т.е. при снятии константности запись будет вестить не в область где хранятся реальные данные, а какой-нибудь буфер (кеш) который возвращают const версии. типа того
Re[2]: Вопрос по снятию константности c const_iterator
От:
Аноним
Дата:
23.01.08 13:26
Оценка:
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Аноним, Вы писали:
E>AFAIK есть, так как second -- это lvalue.
так то оно так, но где гарантия, что в одной из реализаций библиотеки const_iterator будет возращать итератор в буфере (кеше) в который вообще бессмысленно вести запись, т.к представляет собой динамически изменяемый слепок реальных данных.
E>Но IMHO
Здравствуйте, Аноним, Вы писали:
E>>AFAIK есть, так как second -- это lvalue. А>так то оно так, но где гарантия, что в одной из реализаций библиотеки const_iterator будет возращать итератор в буфере (кеше) в который вообще бессмысленно вести запись, т.к представляет собой динамически изменяемый слепок реальных данных.
Дык я про то же
Другое дело, что есть подозрение, что это не нужно не для чего, но гарантий нет, конечно...
E>>Но IMHO
так и лучше и понятнее и надёжнее защита от изысков реализаций STL:[c]template <typename Var, TID> А>интересно, спасибо
Всегда пожалуйста. Обращайся
p. s.
Для спасибо есть кнопочка
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Вопрос по снятию константности c const_iterator
Здравствуйте, Erop, Вы писали:
E>Правда какие-нибудь проксистроители могут что-то такое нарожать, но на первый взгляд дырок не видно.
Поскольку const_iterator — это суперкласс iterator (в смысле LSP), даже если там прокси используются, то в общем случае лучше кастить от неконстантного к константному.
class Foo
{
public:
Value const& get(Key k) const { return const_cast<Foo&>(*this).get(k); }
Value& get(Key k); // здесь программист должен дать гарантии, что сам объект не меняется
};
Естественно, что эти гарантии — достаточно произвольны. Например, если считается, что образы отсутствующих ключей — это дефолтные значения, то можно спокойно сделать mutable map и пользоваться оператором [], который при промахе добавляет элемент.
Или же, раз мы всё равно в шаблоне — то написать шаблон функции.