TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #829 4.65K
Бага обнаружена!
#опытным

Проблема в текущей реализации

template <typename T>
class Vector {
private:
T *m_data;
T *m_endSize;
T *m_endCapacity;

public:
// Use a different type "U to support const and non-const
template <typename U>
class Iterator {
private:
U *m_ptr;

public:
Iterator(U *ptr) : m_ptr{ptr} {}
U &operator*() const { return m_ptr; }
};

template <typename Self>
auto begin(this Self &&self) {
return Iterator(self.m_data);
}
};


заключается в том, что константность не правильно распространяется через итератор при работе с const-объектами Vector. Давайте по порядку

Когда мы имеем const Vector<T>, поле m_data становится T* const (константный указатель на T), а не const T* (указатель на константный T). Так называемая синтаксическая или поверхностная константность.

В текущей реализации, когда вызывается begin() на const-объекте:
Self выводится как const Vector<T>&

self.m_data имеет тип T const

Шаблонный вывод типов в форме CTAD отбрасывает верхнеуровневую константность: для Iterator создает Iterator<T>, а не Iterator<const T>

В результате мы получаем итератор, который позволяет изменять элементы, даже когда Vector константный.

То есть, такой код становится вполне валиден:

const Vector<int> vec{1, 2, 3};
auto it = vec.begin();
*it = 2;


Что не есть хорошо.

Выходом тут будет не использовать CTAD, а явно и гибко задавать тип шаблонного параметра на основе константности self и нескольких трейтов:

template<typename Self>
auto begin(this Self&& self)
{
using value_type = std::conditional_t<
std::is_const_v<std::remove_reference_t<Self>>,
const T,
T>;
return Iterator<value_type>(std::forward<Self>(self).m_data);
}


По пути еще чуть-чуть причесываем передачу универсальной ссылки через std::forward.

Fix the problem. Stay cool.

#template #cppcore
  • 👍 22
  • ❤ 12
  • 🔥 5
  • ❤‍🔥 3
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →