Change History (3)

comment:1 Changed 4 years ago by Дмитрий Свиридкин

Owner: changed from Дмитрий Свиридкин to Денис Лочмелис
Type: ожидается проверкаожидаются исправления

Менять публичные интерфейсы (даже если в них такая оказия случилась) просто так нельзя

src/main.cpp:21:15: error: ‘my_vector’ does not name a type; did you mean ‘my_vector_nsp’?
   21 | using myvec = my_vector::my_vector<T>;

в *_impl.h не надо подключать исходный заголовок

include/my_vector.h:56:6: error: ‘ostream’ in namespace ‘std’ does not name a type
   56 | std::ostream& operator<<(std::ostream& ostr, const my_vector<T>& vec) noexcept;

template <typename T>
void my_vector<T>::my_vector_impl::swap(my_vector_impl&& other) noexcept {

Своп с такой сигнатурой обычно не делают. Потому что это move-присваивание, а не swap. И для реализации такого присваивания достаточно swap для lvalue.

impl.swap(my_vector(other).impl); Тут точно все в порядке с временем жизни? Ради экономии одной строки рисковать наиграть UB при смене стандарта на более ранний?

noexceptы там, где их быть не должно, приводят к UB. Ищите.

resize нарушает строгую гарантию исключений.

Last edited 4 years ago by Дмитрий Свиридкин (previous) (diff)

comment:2 Changed 4 years ago by Денис Лочмелис

Owner: changed from Денис Лочмелис to Дмитрий Свиридкин
Version: 1.02.0

Названия вернул, заголовок убрал.

Такой swap необходим для как раз следующей проблемы. Я думал-думал, так и не понял, что за проблема с временем жизни... Так что и это, и swap для rvalue пришлось оставить.

Убрал два noexcept. Починил resize.

Придумал способ тестирования на утечки: рандомно кидать исключение в конструкторе Product'а. Потратил 2 часа на то, чтобы понять, что такой объект сам базовую гарантию не выполняет и в утечках вектор не виноват. От этого осталась закомменченная функция.

comment:3 Changed 4 years ago by Дмитрий Свиридкин

Resolution: задача сдана
Status: assignedclosed
include/my_vector.h:56:6: error: ‘ostream’ in namespace ‘std’ does not name a type
   56 | std::ostream& operator<<(std::ostream& ostr, const my_vector<T>& vec) noexcept;
      |      ^~~~~~~
include/my_vector.h:5:1: note: ‘std::ostream’ is defined in header ‘<ostream>’; did you forget to ‘#include <ostream>’?
    4 | #include <cstddef>
  +++ |+#include <ostream>

rc/main.cpp:21:15: error: ‘my_vector’ does not name a type; did you mean ‘my_vector_nsp’?
   21 | using myvec = my_vector::my_vector<T>;

Не надо придумывать себе проблемы и героически их превозмогать, создавая неестественные методы. получать ссылку на поле временного объекта -- код содержащий потенциальные ошибки.
Поэтому такую ерунду:

impl.swap(my_vector(other).impl);

Нужно переписать как

my_vector tmp(other);
impl.swap(tmp.impl);
include/my_vector_impl.h:156:33: note:   initializing argument 1 of ‘void my_vector::my_vector<T>::push_back(T&) [with T = MinimalClass]’
  156 | void my_vector<T>::push_back(T& t) {
      |                              ~~~^
src/main.cpp: In instantiation of ‘void push_vector(myvec<T>&, std::size_t) [with T = int; myvec<T> = my_vector::my_vector<int>; std::size_t = long unsigned int]’:
src/main.cpp:275:16:   required from ‘void test_pop_and_push_back() [with T = int]’
src/main.cpp:849:37:   required from here
src/main.cpp:201:36: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
  201 |         vec.push_back(get_object<T>(i));

push_back нарушает строгую гарантию -- вы сделали реаллокацию, а потом полетело исключение.

        my_vector buf;
        buf.reserve(n);
        reserve(n);
        for (; buf.impl.size < impl.size; buf.impl.size++) {
            buf.impl.data[buf.impl.size] = impl.data[buf.impl.size];
        }
        for (; buf.impl.size < n; buf.impl.size++) {
            new (buf.impl.data + buf.impl.size) T(); // noexcept = false
        }
        impl.swap(buf.impl);
  1. Тут UB. Нельзя использовать оператор присваивания к несозданному объекту.
  2. зачем нужен reserve над текущим вектором, если вы его никак не используете, а потом делаете swap?

6.5

Note: See TracTickets for help on using tickets.