Мой вопрос включает в себя повторное использование кода для алгоритма const
unaware (может использоваться с постоянными или изменяемыми объектами)?Константа против взаимозаменяемых итераторов: один и тот же алгоритм разного кода
Возьмем, к примеру, итераторы 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-ness?
* «Основное отличие заключается в том, что' const_iterator' не может быть использованы для записи на вектор.»* Я не уверен, если это уместно, но я думаю, что правильное описание является то, что их тип значения Уста-квалифицированы. У них могут быть изменчивые члены и т. Д. – dyp
Соответствует ли это решение шаблону? http://coliru.stacked-crooked.com/a/e81a4a86c4bf0453 – zch
Я думаю, что проблема является одной из проблем с посетителями, упомянутыми здесь: [cppcon 2014: не принимать посетителей] (https://www.youtube.com/watch ? v = QhJguzpZOrk). Однако основная проблема может быть не связана с итераторами и посетителями; речь идет о необходимости писать дубликат кода для функций-членов из-за константы (и класса значений) экземпляра класса. – dyp