Repository: microsoft/terminal
File: src/inc/til/small_vector.h (C/C++)

Code before:
            small_vector{}
        {
            insert(end(), first, last);
        }

        small_vector(std::initializer_list<T> list) :
            small_vector{}
        {
            insert(end(), list.begin(), list.end());
        }

        // NOTE: If an exception is thrown while copying, the vector is left empty.
        small_vector(const small_vector& other) :
            small_vector{}
        {
            operator=(other);
        }

        // NOTE: If an exception is thrown while copying, the vector is left empty.
        small_vector& operator=(const small_vector& other)
        {
            clear();
            reserve(other._size);

            std::uninitialized_copy(other.begin(), other.end(), _uninitialized_begin());
            _size = other._size;

            return *this;
        }

        small_vector(small_vector&& other) noexcept :
            small_vector{}
        {
            operator=(std::move(other));
        }

        small_vector& operator=(small_vector&& other) noexcept
        {
            std::destroy(begin(), end());
            if (_capacity != N)
            {
                _deallocate(_data);
            }

            if (other._capacity == N)
            {
                _data = &_buffer[0];
                _capacity = N;
                _size = other._size;
                // The earlier static_assert(std::is_nothrow_move_constructible_v<T>)
                // ensures that we don't exit in a weird state with invalid `_size`.

Review comment (suggestion):
These 3 lines are now moved 1:1 into `_copy_assign`. This allows us to call `_copy_assign` without a prior `clear` in the constructor, because a newly constructed vector can't possibly have anything that needs to be cleared.

This makes the diff large, but actually barely anything changed.

Code after:
        template<std::input_iterator InputIt>
        small_vector(InputIt first, InputIt last) :
            small_vector{}
        {
            insert(end(), first, last);
        }

        small_vector(std::initializer_list<T> list) :
            small_vector{}
        {
            insert(end(), list.begin(), list.end());
        }

        // NOTE: If an exception is thrown while copying, the vector is left empty.
        small_vector(const small_vector& other) :
            small_vector{}
        {
            _copy_assign(other);
        }

        // NOTE: If an exception is thrown while copying, the vector is left empty.
        small_vector& operator=(const small_vector& other)
        {
            if (this != &other)
            {
                clear();
                _copy_assign(other);
            }

            return *this;
        }

        small_vector(small_vector&& other) noexcept
        {
            _move_assign(other);
        }

        small_vector& operator=(small_vector&& other) noexcept
        {
            if (this != &other)
            {
                std::destroy(begin(), end());
                if (_capacity != N)
                {
                    _deallocate(_data);
                }

                _move_assign(other);
            }

            return *this;