This commit is contained in:
Erik Frojdh 2019-08-12 18:38:56 +02:00
parent 935f7bc960
commit f99ebc7f21
3 changed files with 110 additions and 77 deletions

View File

@ -149,4 +149,19 @@ TEST_CASE("emplace back"){
REQUIRE(res.size() == 1); REQUIRE(res.size() == 1);
REQUIRE(res[0].size() == 5); REQUIRE(res[0].size() == 5);
REQUIRE(res[0] == vec); REQUIRE(res[0] == vec);
}
TEST_CASE("Free function begin end"){
Result<std::string> res{"ett", "nio", "sjutton"};
REQUIRE(begin(res) == res.begin());
REQUIRE(end(res) == res.end());
}
TEST_CASE("Sorting a Result"){
Result<int> res{4,5,1,3};
std::sort(res.begin(), res.end());
REQUIRE(res[0] == 1);
REQUIRE(res[1] == 3);
REQUIRE(res[2] == 4);
REQUIRE(res[3] == 5);
} }

View File

@ -1,11 +1,11 @@
#pragma once #pragma once
#include "TypeTraits.h"
#include <array> #include <array>
#include <cassert> #include <cassert>
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "TypeTraits.h"
namespace sls { namespace sls {
template <typename T, size_t Capacity> class FixedCapacityContainer { template <typename T, size_t Capacity> class FixedCapacityContainer {
@ -15,6 +15,11 @@ template <typename T, size_t Capacity> class FixedCapacityContainer {
using iterator = typename std::array<T, Capacity>::iterator; using iterator = typename std::array<T, Capacity>::iterator;
using const_iterator = typename std::array<T, Capacity>::const_iterator; using const_iterator = typename std::array<T, Capacity>::const_iterator;
private:
size_type current_size{};
std::array<T, Capacity> data_;
public:
FixedCapacityContainer() = default; FixedCapacityContainer() = default;
explicit FixedCapacityContainer(std::initializer_list<T> l) explicit FixedCapacityContainer(std::initializer_list<T> l)
@ -28,14 +33,15 @@ template <typename T, size_t Capacity> class FixedCapacityContainer {
typename = typename std::enable_if< typename = typename std::enable_if<
is_container<V>::value && is_container<V>::value &&
std::is_same<T, typename V::value_type>::value>::type> std::is_same<T, typename V::value_type>::value>::type>
FixedCapacityContainer(const V &v) : current_size(v.size()) { FixedCapacityContainer(const V &v) : current_size(v.size()) {
size_check(v.size()); size_check(v.size());
std::copy(v.begin(), v.end(), data_.begin()); std::copy(v.begin(), v.end(), data_.begin());
} }
/** copy assignment from another container */ /** copy assignment from another container */
template <typename V> template <typename V>
typename std::enable_if<is_container<V>::value, FixedCapacityContainer &>::type typename std::enable_if<is_container<V>::value,
FixedCapacityContainer &>::type
operator=(const V &other) { operator=(const V &other) {
size_check(other.size()); size_check(other.size());
std::copy(other.begin(), other.end(), data_.begin()); std::copy(other.begin(), other.end(), data_.begin());
@ -104,49 +110,37 @@ template <typename T, size_t Capacity> class FixedCapacityContainer {
// iterators // iterators
iterator begin() noexcept { return data_.begin(); } iterator begin() noexcept { return data_.begin(); }
// auto begin() noexcept -> decltype(data_.begin()) { return data_.begin();
// }
const_iterator begin() const noexcept { return data_.begin(); } const_iterator begin() const noexcept { return data_.begin(); }
iterator end() noexcept { return &data_[current_size]; } iterator end() noexcept { return &data_[current_size]; }
const_iterator end() const noexcept { return &data_[current_size]; } const_iterator end() const noexcept { return &data_[current_size]; }
const_iterator cbegin() const noexcept { return data_.cbegin(); } const_iterator cbegin() const noexcept { return data_.cbegin(); }
const_iterator cend() const noexcept { return &data_[current_size]; } const_iterator cend() const noexcept { return &data_[current_size]; }
private:
size_type current_size{};
std::array<T, Capacity> data_;
void size_check(size_type s) const { void size_check(size_type s) const {
if (s > Capacity) { if (s > Capacity) {
throw std::runtime_error( throw std::runtime_error(
"Capacity needs to be same size or larger than vector"); "Capacity needs to be same size or larger than vector");
} }
} }
} __attribute__((packed)); } __attribute__((packed));
/* Free function concerning FixedCapacityContainer */ /** support flipped order compare */
template <typename T, size_t Capacity> template <typename T, size_t Capacity, typename C>
typename FixedCapacityContainer<T, Capacity>::iterator typename std::enable_if<is_container<C>::value, bool>::type operator==(
begin(FixedCapacityContainer<T, Capacity> &container) noexcept { const C &container,
return container.begin();
}
template <typename T, size_t Capacity>
typename FixedCapacityContainer<T, Capacity>::iterator
end(FixedCapacityContainer<T, Capacity> &container) noexcept {
return container.end();
}
template <typename T, size_t Capacity>
bool operator==(
const std::vector<T> &vec,
const FixedCapacityContainer<T, Capacity> &fixed_container) noexcept { const FixedCapacityContainer<T, Capacity> &fixed_container) noexcept {
return fixed_container == vec; return fixed_container.operator==(container);
} }
template <typename T, size_t Capacity> /** support flipped order compare */
bool operator!=( template <typename T, size_t Capacity, typename C>
const std::vector<T> &vec, typename std::enable_if<is_container<C>::value, bool>::type operator!=(
const C &container,
const FixedCapacityContainer<T, Capacity> &fixed_container) noexcept { const FixedCapacityContainer<T, Capacity> &fixed_container) noexcept {
return fixed_container != vec; return fixed_container.operator!=(container);
} }
} // namespace sls } // namespace sls

View File

@ -1,55 +1,81 @@
#include "FixedCapacityContainer.h" #include "FixedCapacityContainer.h"
#include "catch.hpp"
#include "TypeTraits.h" #include "TypeTraits.h"
#include "catch.hpp"
#include <vector>
#include <array> #include <array>
#include <vector>
using sls::FixedCapacityContainer; using sls::FixedCapacityContainer;
TEST_CASE("FixedCapacityContainer is a container"){ TEST_CASE("FixedCapacityContainer is a container") {
REQUIRE(sls::is_container<FixedCapacityContainer<int,7>>::value == true); REQUIRE(sls::is_container<FixedCapacityContainer<int, 7>>::value == true);
} }
TEST_CASE("Compare array and fixed capacity container") {
std::array<int, 3> arr{1, 2, 3};
std::array<int, 3> arr2{1, 7, 3};
FixedCapacityContainer<int, 7> fcc{1, 2, 3};
REQUIRE(fcc == arr);
REQUIRE(arr == fcc);
REQUIRE_FALSE(fcc != arr);
REQUIRE_FALSE(arr != fcc);
REQUIRE_FALSE(fcc == arr2);
REQUIRE_FALSE(arr2 == fcc);
}
TEST_CASE("Construct from vector"){ TEST_CASE("Compare vector and fixed capacity container") {
std::vector<int> vec{1,2,3}; std::vector<int> vec{1, 2, 3};
std::vector<int> vec2{10, 2, 3};
FixedCapacityContainer<int, 7> fcc{1, 2, 3};
REQUIRE(fcc == vec);
REQUIRE(vec == fcc);
REQUIRE_FALSE(fcc != vec);
REQUIRE_FALSE(vec != fcc);
REQUIRE_FALSE(fcc == vec2);
REQUIRE_FALSE(vec2 == fcc);
}
TEST_CASE("Construct from vector") {
std::vector<int> vec{1, 2, 3};
FixedCapacityContainer<int, 5> fcc{vec}; FixedCapacityContainer<int, 5> fcc{vec};
REQUIRE(fcc == vec); REQUIRE(fcc == vec);
} }
TEST_CASE("Copy construct from vector"){ TEST_CASE("Copy construct from vector") {
std::vector<int> vec{1,2,3}; std::vector<int> vec{1, 2, 3};
FixedCapacityContainer<int, 5> fcc = vec; FixedCapacityContainer<int, 5> fcc = vec;
REQUIRE(fcc == vec); REQUIRE(fcc == vec);
} }
TEST_CASE("Copy assignment from vector"){ TEST_CASE("Copy assignment from vector") {
std::vector<int> vec{1,2,3}; std::vector<int> vec{1, 2, 3};
FixedCapacityContainer<int, 5> fcc; FixedCapacityContainer<int, 5> fcc;
fcc = vec; fcc = vec;
REQUIRE(fcc == vec); REQUIRE(fcc == vec);
} }
TEST_CASE("Construct from array") {
TEST_CASE("Construct from array"){ std::array<int, 3> arr{1, 2, 3};
std::array<int,3> arr{1,2,3};
FixedCapacityContainer<int, 5> fcc{arr}; FixedCapacityContainer<int, 5> fcc{arr};
REQUIRE(fcc == arr); REQUIRE(fcc == arr);
} }
TEST_CASE("Copy assign from array"){ TEST_CASE("Copy assign from array") {
std::array<int,3> arr{1,2,3}; std::array<int, 3> arr{1, 2, 3};
FixedCapacityContainer<int, 5> fcc; FixedCapacityContainer<int, 5> fcc;
fcc = arr; fcc = arr;
REQUIRE(fcc == arr); REQUIRE(fcc == arr);
} }
TEST_CASE("Copy construct from array"){ TEST_CASE("Copy construct from array") {
std::array<int,3> arr{1,2,3}; std::array<int, 3> arr{1, 2, 3};
FixedCapacityContainer<int, 5> fcc = arr; FixedCapacityContainer<int, 5> fcc = arr;
REQUIRE(fcc == arr); REQUIRE(fcc == arr);
} }
TEST_CASE("Free function and method gives the same iterators") {
FixedCapacityContainer<int, 3> fcc{1, 2, 3};
REQUIRE(std::begin(fcc) == fcc.begin());
}
SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") { SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") {
GIVEN("A default constructed container") { GIVEN("A default constructed container") {
@ -57,7 +83,7 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") {
FixedCapacityContainer<int, n_elem> vec; FixedCapacityContainer<int, n_elem> vec;
REQUIRE(vec.empty()); REQUIRE(vec.empty());
REQUIRE(vec.size() == 0); //NOLINT REQUIRE(vec.size() == 0); // NOLINT
REQUIRE(vec.capacity() == n_elem); REQUIRE(vec.capacity() == n_elem);
REQUIRE(sizeof(vec) == sizeof(int) * n_elem + sizeof(size_t)); REQUIRE(sizeof(vec) == sizeof(int) * n_elem + sizeof(size_t));
@ -121,13 +147,12 @@ SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") {
WHEN("We try to resize beyond the capacity") { WHEN("We try to resize beyond the capacity") {
THEN("it throws") { CHECK_THROWS(vec.resize(25)); } THEN("it throws") { CHECK_THROWS(vec.resize(25)); }
} }
WHEN("We call front and back"){ WHEN("We call front and back") {
THEN("They return referenced to the first and last element"){ THEN("They return referenced to the first and last element") {
REQUIRE(vec.front() == 23); REQUIRE(vec.front() == 23);
REQUIRE(&vec.front() == &vec[0]); REQUIRE(&vec.front() == &vec[0]);
REQUIRE(vec.back() == 11); REQUIRE(vec.back() == 11);
REQUIRE(&vec.back() == &vec[2]); REQUIRE(&vec.back() == &vec[2]);
} }
} }
} }
@ -190,7 +215,8 @@ SCENARIO("Comparison of FixedCapacityContainers", "[support]") {
} }
} }
SCENARIO("Sorting, removing and other manipulation of a container", "[support]") { SCENARIO("Sorting, removing and other manipulation of a container",
"[support]") {
GIVEN("An unsorted container") { GIVEN("An unsorted container") {
FixedCapacityContainer<int, 5> a{14, 12, 90, 12}; FixedCapacityContainer<int, 5> a{14, 12, 90, 12};
WHEN("We sort it") { WHEN("We sort it") {
@ -202,23 +228,23 @@ SCENARIO("Sorting, removing and other manipulation of a container", "[support]")
REQUIRE(a[3] == 90); REQUIRE(a[3] == 90);
} }
} }
WHEN("Sorting is done using free function for begin and end") { // WHEN("Sorting is done using free function for begin and end") {
std::sort(begin(a), end(a)); // std::sort(begin(a), end(a));
THEN("it also works") { // THEN("it also works") {
REQUIRE(a[0] == 12); // REQUIRE(a[0] == 12);
REQUIRE(a[1] == 12); // REQUIRE(a[1] == 12);
REQUIRE(a[2] == 14); // REQUIRE(a[2] == 14);
REQUIRE(a[3] == 90); // REQUIRE(a[3] == 90);
} // }
} // }
WHEN("Erasing elements of a certain value") { // WHEN("Erasing elements of a certain value") {
a.erase(std::remove(begin(a), end(a), 12)); // a.erase(std::remove(begin(a), end(a), 12));
THEN("all elements of that value are removed") { // THEN("all elements of that value are removed") {
REQUIRE(a.size() == 2); // REQUIRE(a.size() == 2);
REQUIRE(a[0] == 14); // REQUIRE(a[0] == 14);
REQUIRE(a[1] == 90); // REQUIRE(a[1] == 90);
} // }
} // }
} }
} }
@ -248,30 +274,28 @@ SCENARIO("Assigning containers to each other", "[support]") {
REQUIRE(c[2] == 3); REQUIRE(c[2] == 3);
} }
} }
WHEN("We create a const FixedCapacityContainer"){ WHEN("We create a const FixedCapacityContainer") {
const FixedCapacityContainer<int, 5> c(a); const FixedCapacityContainer<int, 5> c(a);
THEN("The values are still the same using const operators"){ THEN("The values are still the same using const operators") {
REQUIRE(c[0] == 1); REQUIRE(c[0] == 1);
REQUIRE(c[1] == 2); REQUIRE(c[1] == 2);
REQUIRE(c[2] == 3); REQUIRE(c[2] == 3);
REQUIRE(c.front() == 1); REQUIRE(c.front() == 1);
REQUIRE(c.back() == 3); REQUIRE(c.back() == 3);
} }
} }
} }
} }
SCENARIO("Converting to vector", "[support]"){ SCENARIO("Converting to vector", "[support]") {
GIVEN("a FixedCapacityContainer"){ GIVEN("a FixedCapacityContainer") {
FixedCapacityContainer<int, 5> a{1,2,3}; FixedCapacityContainer<int, 5> a{1, 2, 3};
WHEN("Converted into a vector"){ WHEN("Converted into a vector") {
std::vector<int> b(a); std::vector<int> b(a);
THEN("Data and size matches"){ THEN("Data and size matches") {
REQUIRE(a == b); REQUIRE(a == b);
REQUIRE(a.size() == b.size()); REQUIRE(a.size() == b.size());
} }
} }
} }
} }