Skip to content

Commit 515c6d3

Browse files
authored
Fix static vector bug (#144)
* pop_back, clear and destructor now all call destructors of elements * Updated CI script for MacOS * Added unit tests for static_vector * Replaced unique_ptr in test with a shared_ptr
1 parent 23988b9 commit 515c6d3

File tree

5 files changed

+90
-7
lines changed

5 files changed

+90
-7
lines changed

.github/workflows/skyr-url-ci.yml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,9 @@ jobs:
270270
chmod +x llvm.sh
271271
sudo ./llvm.sh 10
272272
273-
- name: Install vcpkg (Linux/MacOS)
274-
id: vcpkg_linux_macos
275-
if: startsWith(matrix.config.os, 'ubuntu') || startsWith(matrix.config.os, 'macos')
273+
- name: Install vcpkg (Linux)
274+
id: vcpkg_linux
275+
if: startsWith(matrix.config.os, 'ubuntu')
276276
shell: bash
277277
run: |
278278
mkdir -p ${GITHUB_WORKSPACE}/vcpkg
@@ -285,6 +285,22 @@ jobs:
285285
./bootstrap-vcpkg.sh
286286
./vcpkg install tl-expected range-v3 catch2 nlohmann-json fmt
287287
288+
- name: Install vcpkg (MacOS)
289+
id: vcpkg_macos
290+
if: startsWith(matrix.config.os, 'macos')
291+
shell: bash
292+
run: |
293+
brew install pkg-config
294+
mkdir -p ${GITHUB_WORKSPACE}/vcpkg
295+
cd ${GITHUB_WORKSPACE}/vcpkg
296+
git init
297+
git remote add origin https://github.com/microsoft/vcpkg.git
298+
git fetch origin master
299+
git checkout -b master origin/master
300+
export
301+
./bootstrap-vcpkg.sh
302+
./vcpkg install tl-expected range-v3 catch2 nlohmann-json fmt
303+
288304
- name: Install vcpkg (Windows)
289305
id: vcpkg_windows
290306
if: startsWith(matrix.config.os, 'windows')

include/skyr/v1/containers/static_vector.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class static_vector {
5252
/// Constructor
5353
constexpr static_vector() = default;
5454

55+
~static_vector() {
56+
clear();
57+
}
58+
5559
/// Gets the first const element in the vector
5660
/// \return a const T &
5761
/// \pre `size() > 0`
@@ -83,7 +87,7 @@ class static_vector {
8387
///
8488
/// \param value
8589
/// \return
86-
/// \pre `size() < `capacity()`
90+
/// \pre `size() < capacity()`
8791
/// \post `size() > 0 && size() <= capacity()`
8892
constexpr auto push_back(const_reference value) noexcept -> reference {
8993
impl_[size_++] = value;
@@ -94,19 +98,20 @@ class static_vector {
9498
/// \tparam Args
9599
/// \param args
96100
/// \return
97-
/// \pre `size() < `capacity()`
101+
/// \pre `size() < capacity()`
98102
/// \post `size() > 0 && size() <= capacity()`
99103
template <class... Args>
100104
constexpr auto emplace_back(Args &&... args)
101105
noexcept(std::is_trivially_move_assignable_v<T>) -> reference {
102-
impl_[size_++] = value_type{args...};
106+
impl_[size_++] = value_type{std::forward<Args>(args)...};
103107
return impl_[size_ - 1];
104108
}
105109

106110
///
107111
/// \pre `size() > 0`
108112
constexpr void pop_back() noexcept {
109113
--size_;
114+
impl_[size_].~T();
110115
}
111116

112117
///
@@ -140,8 +145,11 @@ class static_vector {
140145
}
141146

142147
///
148+
/// \post size() == 0
143149
constexpr void clear() noexcept {
144-
size_ = 0;
150+
while (size_) {
151+
pop_back();
152+
}
145153
}
146154

147155
///

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function(skyr_create_test file_name output_dir test_name)
3333
set(test_name ${test} PARENT_SCOPE)
3434
endfunction()
3535

36+
add_subdirectory(containers)
3637
add_subdirectory(unicode)
3738
add_subdirectory(domain)
3839
add_subdirectory(percent_encoding)

tests/containers/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) Glyn Matthews 2020.
2+
# Distributed under the Boost Software License, Version 1.0.
3+
# (See accompanying file LICENSE_1_0.txt or copy at
4+
# http://www.boost.org/LICENSE_1_0.txt)
5+
6+
foreach (
7+
file_name
8+
static_vector_tests.cpp)
9+
skyr_create_test(${file_name} ${PROJECT_BINARY_DIR}/tests/container test_name)
10+
endforeach ()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2020 Glyn Matthews.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
#include <memory>
7+
#define CATCH_CONFIG_MAIN
8+
#include <catch2/catch.hpp>
9+
#include <skyr/v1/containers/static_vector.hpp>
10+
11+
12+
struct test_destructor_call {
13+
bool *destructed = nullptr;
14+
15+
explicit test_destructor_call(bool *destructed)
16+
: destructed(destructed) {
17+
*destructed = false;
18+
}
19+
20+
test_destructor_call(const test_destructor_call &) = delete;
21+
test_destructor_call &operator=(const test_destructor_call &) = delete;
22+
test_destructor_call(test_destructor_call &&) = delete;
23+
test_destructor_call &operator=(test_destructor_call &&) = delete;
24+
25+
~test_destructor_call() {
26+
*destructed = true;
27+
}
28+
};
29+
30+
TEST_CASE("pop back calls destructor", "[containers]") {
31+
auto destructed = false;
32+
33+
auto vector = skyr::static_vector<std::shared_ptr<test_destructor_call>, 8>{};
34+
vector.emplace_back(std::make_shared<test_destructor_call>(&destructed));
35+
CHECK_FALSE(destructed);
36+
vector.pop_back();
37+
CHECK(destructed);
38+
}
39+
40+
TEST_CASE("clear calls destructor", "[containers]") {
41+
auto destructed = false;
42+
43+
auto vector = skyr::static_vector<std::shared_ptr<test_destructor_call>, 8>{};
44+
vector.emplace_back(std::make_shared<test_destructor_call>(&destructed));
45+
CHECK_FALSE(destructed);
46+
vector.clear();
47+
CHECK(destructed);
48+
}

0 commit comments

Comments
 (0)