Я попытался максимально упростить ситуацию.const iterator зависит от функции begin()
В основном у меня есть класс, который представляет собой динамический Array
(здесь показан как class Array
с размером 4), а во-вторых класс, который является HashMap, и имеет Array of Arrays
в качестве члена (здесь представленного class Bar
).
Оба класса реализуют begin()
и end()
, поэтому вы можете использовать цикл foreach для итерации по всем элементам.
Тип итератора Array
- это просто T*
и const T*
для варианта const. Для Bar
есть специальный class Iterator
, который правильно выполняет итерации по всем элементам Array<Array<T>>
. Теперь вы должны взглянуть на классы, которые я предоставил, чтобы вы знали, о чем я говорю.
Но теперь есть проблема, когда я называю
bar.begin()
наconst Bar
объекта
Класс Итератор автоматически определяет типы ArrayIterator
и ElementIterator
(через decltype Т :: начать()) , потому что в моем реальном приложении почти все шаблоны, и поэтому я не знаю точного типа заранее.
Я понял, что проблема заключается в том, что decltype(((T*)nullptr)->begin())
всегда выбирает функцию non-const begin() функции T, что абсолютно имеет смысл, поскольку я не написал (const T*)nullptr
.
Если теперь я называю это из константного контекста, она будет не назначать const T*
как data.last().end()
к внутреннему T*
от decltype, который на самом деле должен быть const T*
.
я могу обойти эту проблему, объявив второй класс ConstIterator
, который делает все так же, как неконстантные один, но использует (const Array<T>*)nullptr
и (const T*)nullptr
внутри заявления decltype.
Итак, что я могу сделать без копирования всей панели: класс Iterator?
упрощенный код:
template<class T>
class Array
{
T data[4];
T last() { return data[3]; }
T* begin() { return data; };
T* end() { return data + 4; };
const T* begin() const { return data; };
const T* end() const { return data + 4; };
}
template<class T>
class Bar
{
class Iterator
{
using ArrayIterator = decltype(((Array<T>*)nullptr)->begin());
using ElementIterator = decltype(((T*)nullptr)->begin());
Iterator(const ArrayIterator& beg, const ArrayIterator& end)
{
//initialize the iterator to the first element of the first array
//(and rembember end)
};
Iterator(const ElementIterator& cur)
{
//initialize the iterator to the current element
};
//++ will iterate go to next element and eventually jump to the next array.
//== returns true if the current element is the same
};
Array<T> data;
Iterator begin() { return Iterator(data.begin(), data.end()); };
Iterator end() { return Iterator(data.last().end()); };
Iterator begin() const { return Iterator(data.begin(), data.end()); };
Iterator end() const { return Iterator(data.last().end()); };
};
Не используйте для этого const_cast. –