Skip to content

Latest commit

 

History

History
109 lines (82 loc) · 2.14 KB

351.md

File metadata and controls

109 lines (82 loc) · 2.14 KB
Info

Example

int main() {
    std::inplace_vector<int, 2> v{};
    assert(v.empty());

    v.push_back(1);
    assert(1 == v.size());

    v.push_back(2);
    assert(2 == v.size());

    v.push_back(3); // throws
}

https://godbolt.org/z/o365eWeEb

Puzzle

  • Can you implement simplified constexpr version of inplace_vector?
template<class T, auto Size>
class inplace_vector; // TODO

static_assert([] {
    inplace_vector<int, 1> v{};
    v.push_back(1);
    return v.size();
}() == 1);

static_assert([] {
    inplace_vector<int, 2> v{};
    v.push_back(1);
    v.push_back(2);
    return v.size();
}() == 2);

static_assert([] {
    inplace_vector<int, 2> v{};
    v.push_back(4);
    v.push_back(2);
    return v[0] + v[1];
}() == 6);

// should not compile
static_assert([] {
    inplace_vector<int, 2> v{};
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    return v.size();
}() == 2)

https://godbolt.org/z/z51faxfa9

Solutions

template <class T, auto Size>
struct inplace_vector {
    constexpr void push_back(T value) { data_[index_++] = value; }
    constexpr const auto& operator[](auto index) const { return data_[index]; }
    constexpr auto size() const { return index_; }
    constexpr auto clear() { index_ = {}; }

   private:
    std::array<T, Size> data_{};
    std::size_t index_{};
};

https://godbolt.org/z/acsa59PdG

template <class T, auto Size>
class inplace_vector {
   public:
    constexpr T& push_back(const T& t) {
        if (size_ == Size) {
            throw std::bad_alloc();
        }
        return arr_[size_++].emplace(t);
    }

    constexpr std::size_t size() const { return size_; }

    constexpr T& operator[](std::size_t idx) { return *arr_[idx]; }

   private:
    std::array<std::optional<T>, Size> arr_;
    std::size_t size_ = 0;
};

https://godbolt.org/z/scz4EfTa5