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
}
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)
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_{};
};
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;
};