Мой вопрос касается того, как повторно использовать код для алгоритма, который const
не знает (может использоваться с постоянными или изменяемыми объектами)?
Возьмем, к примеру, итераторы std::vector
.
Есть два класса итераторов, использующих схожие методы: std::vector::iterator
и std::vector::const_iterator
.
Оба итератора указывают на слоты в векторе или за его пределами (например, std::vector::end()
).
Оба они имеют методы увеличения и уменьшения. Основное отличие состоит в том, что const_iterator
нельзя использовать для записи в вектор.
Если бы я писал код для итераторов, как бы я мог использовать общие методы iterator
и const_iterator
, которые не зависели бы от константности операции доступа?
В моем текущем коде я дублирую код для методов for_each
и visit
из-за разницы в доступности. Цикл for_each
— это тот же цикл for
, разница в том, что один применяет const_visitor, а другой применяет mutable_visitor.
struct Object;
struct Const_Visitor
{
// Visit function cannot modified the given object.
virtual void visit(const Object& o) = 0;
};
struct Mutable_Visitor
{
// The visit function may modify the given object;
virtual void visit(Object& o) = 0;
};
struct Container
{
const unsigned int LIMIT = 16;
Object obj_container[LIMIT];
// Apply the read-only (constant) visitor
// to each object in the container
void for_each(Const_Visitor& cv) const
{
// Note: this loop management is the same
// as the loop management for the mutable for_each() method.
for (unsigned int i = 0; i < LIMIT; ++i)
{
cv.visit(obj_container[i]);
}
}
// Apply the read/write (mutable) visitor
// to each object in the container.
void for_each(Mutable_Visitor& mv)
{
// Note: this loop management is the same
// as the loop management for the const for_each() method.
for (unsigned int i = 0; i < LIMIT; ++i)
{
mv.visit(obj_container[i]);
}
}
};
В приведенном выше примере механика одинакова для обеих функций for_each
. Меняется только посетитель. Те же слоты в массиве передаются функциям visit
.
Это можно было бы немного изменить, используя одного посетителя с двумя методами visit
, но фундаментальная проблема все еще существует.
struct Object;
struct Single_Visitor
{
// Method can't modify the object.
virtual void visit(const Object& o) = 0;
// Method may modify the object.
virtual void visit(Object& o) = 0;
};
struct Container
{
const unsigned int LIMIT = 16;
Object obj_container[LIMIT];
// Apply a visitor to each item in container.
void for_each(Single_Visitor& sv) const
{
for (unsigned int i; i < LIMIT; ++i)
{
// Should call the visit method,
// constant object.
sv.visit(obj_container[i]);
}
}
// Apply a visitor to each item in container.
void for_each(Single_Visitor& sv)
{
for (unsigned int i; i < LIMIT; ++i)
{
// Should call the visit method,
// mutable object.
sv.visit(obj_container[i]);
}
}
};
С классом посетителя, который имеет два метода (по сравнению с двумя отдельными классами), методы контейнера for_each
по-прежнему имеют ту же механику. Цикл такой же, просто вызывается другой метод.
Итак, есть ли способ иметь один цикл for_each
, который вызывает соответствующий посетитель на основе константы?
const_iterator
нельзя использовать для записи в вектор. Я не уверен, что это уместно, но я думаю, что правильное описание состоит в том, что их тип значения является const-qualified. Они могут иметь изменяемые члены и т.д. - person dyp   schedule 10.11.2014