Compare commits

..

No commits in common. "5e1bda2715f0b2e8e4bfca5f1090cb2bae630048" and "4e448f2f852b4b1c25bee43614577a637cf72fa4" have entirely different histories.

4 changed files with 23 additions and 304 deletions

View File

@ -114,7 +114,7 @@ namespace cc {
[[nodiscard]] constexpr size_type capacity() const noexcept { return _len; } [[nodiscard]] constexpr size_type capacity() const noexcept { return _len; }
[[nodiscard]] constexpr size_type size() const noexcept { return _size; } [[nodiscard]] constexpr size_type size() const noexcept { return _size; }
constexpr void clear(); constexpr void clear() { std::fill(begin(), end(), T()); }
constexpr iterator insert(const_iterator pos, const T& value); constexpr iterator insert(const_iterator pos, const T& value);
constexpr iterator insert(const_iterator pos, T&& value); constexpr iterator insert(const_iterator pos, T&& value);
@ -386,59 +386,44 @@ namespace cc {
return _arr[pos]; return _arr[pos];
} }
template<typename T, std::size_t N>
constexpr void const_vector<T, N>::clear()
{
std::destroy(begin(), end());
_size = 0;
}
template<typename T, std::size_t N> template<typename T, std::size_t N>
constexpr const_vector<T, N>::iterator const_vector<T, N>::insert(const_vector::const_iterator pos, const T &value) constexpr const_vector<T, N>::iterator const_vector<T, N>::insert(const_vector::const_iterator pos, const T &value)
{ {
if (_size == N) throw std::length_error("No space left in vector"); if (_size == N) throw std::exception();
auto it = const_cast<iterator>(pos); ptrdiff_t i = pos - _arr;
std::move(_arr + i, _arr + _size, _arr + i + 1);
_arr[i] = value;
if (pos != end()) {
std::move_backward(it, end(), end() + 1);
}
*it = value;
++_size; ++_size;
return pos;
return it;
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>
constexpr const_vector<T, N>::iterator const_vector<T, N>::insert(const_vector::const_iterator pos, T &&value) constexpr const_vector<T, N>::iterator const_vector<T, N>::insert(const_vector::const_iterator pos, T &&value)
{ {
if (_size == N) throw std::length_error("No space left in vector"); if (_size == N) throw std::exception();
auto it = const_cast<iterator>(pos); ptrdiff_t i = pos - _arr;
std::move(_arr + i, _arr + _size, _arr + i + 1);
_arr[i] = std::move(value);
if (pos != end()) {
std::move_backward(it, end(), end() + 1);
}
*it = std::forward<value_type>(value);
++_size; ++_size;
return pos;
return it;
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>
constexpr const_vector<T, N>::iterator constexpr const_vector<T, N>::iterator
const_vector<T, N>::insert(const_vector::const_iterator pos, const_vector::size_type count, const T &value) const_vector<T, N>::insert(const_vector::const_iterator pos, const_vector::size_type count, const T &value)
{ {
auto it = const_cast<iterator>(pos); if (count == 0) return pos;
if (_size + count >= N) throw std::exception();
if (count == 0) return it;
if (_size + count > N) throw std::length_error("Not enough space left in vector for " + std::to_string(count) + " elements");
std::move_backward(it, end(), end() + count); std::move(pos, _arr + _size, pos + count);
std::fill(it, it + count, value); std::fill(pos, pos + count, value);
_size += count; _size += count;
return it; return pos;
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>
@ -447,16 +432,16 @@ namespace cc {
const_vector<T, N>::insert(const_vector::const_iterator pos, InputIt first, InputIt last) const_vector<T, N>::insert(const_vector::const_iterator pos, InputIt first, InputIt last)
{ {
auto count = std::distance(first, last); auto count = std::distance(first, last);
auto it = const_cast<iterator>(pos);
if (first == last) return it; if (first == last) return pos;
if (_size + count > N) throw std::length_error("Not enough space left in vector for " + std::to_string(count) + " elements"); if (_size + count >= N) throw std::exception();
std::move_backward(it, end(), end() + count);
std::copy(first, last, it); std::move(pos, _arr + _size, pos + count);
std::copy(first, last, pos);
_size += count; _size += count;
return it; return pos;
} }
template<typename T, std::size_t N> template<typename T, std::size_t N>

View File

@ -33,7 +33,6 @@ constexpr auto make_copy(auto& value) -> std::remove_cvref_t<decltype(value)> {
#define ASSERT(condition, ...) ASSERT_MSG((condition), "Condition (" #condition ") evaluated to false" _LOCATION, __VA_ARGS__) #define ASSERT(condition, ...) ASSERT_MSG((condition), "Condition (" #condition ") evaluated to false" _LOCATION, __VA_ARGS__)
#define ASSERT_MSG(condition, msg, ...) { if (!(condition)) return _ret_val_from_ctx<__VA_ARGS__>(ReturnCode::FAILED, msg); } static_assert(true, "") #define ASSERT_MSG(condition, msg, ...) { if (!(condition)) return _ret_val_from_ctx<__VA_ARGS__>(ReturnCode::FAILED, msg); } static_assert(true, "")
#define ASSERT_THROWS(operation, exception_type, ...) if not consteval { try { operation; ASSERT_MSG(false, #operation " did not throw " #exception_type _LOCATION, __VA_ARGS__); } catch (exception_type &e) {} } static_assert(true, "") #define ASSERT_THROWS(operation, exception_type, ...) if not consteval { try { operation; ASSERT_MSG(false, #operation " did not throw " #exception_type _LOCATION, __VA_ARGS__); } catch (exception_type &e) {} } static_assert(true, "")
#define ASSERT_NOTHROW(operation, exception_type, ...) if not consteval { try { operation; } catch (exception_type &e) { ASSERT_MSG(false, #operation " threw " #exception_type _LOCATION, __VA_ARGS__); } } static_assert(true, "")
template<typename T> template<typename T>
concept StringLike = std::is_convertible_v<T, std::string_view>; concept StringLike = std::is_convertible_v<T, std::string_view>;
@ -67,19 +66,6 @@ constexpr bool all_equal_to(I first, S last, T t) {
return std::ranges::equal(r1, r2); return std::ranges::equal(r1, r2);
} }
template<std::ranges::range R1, std::ranges::range R2>
requires StringLike<std::ranges::range_value_t<R1>> && StringLike<std::ranges::range_value_t<R2>>
constexpr bool ranges_equal(R1 r1, R2 r2) {
auto r1t = r1 | std::ranges::views::transform([](auto&& e) constexpr { return std::string_view(e); });
auto r2t = r2 | std::ranges::views::transform([](auto&& e) constexpr { return std::string_view(e); });
return std::ranges::equal(r1t, r2t);
}
template<std::ranges::range R1, std::ranges::range R2>
constexpr bool ranges_equal(R1 r1, R2 r2) {
return std::ranges::equal(r1, r2);
}
template<std::input_iterator I, std::sentinel_for<I> S, std::ranges::range R> template<std::input_iterator I, std::sentinel_for<I> S, std::ranges::range R>
requires StringLike<std::ranges::range_value_t<R>> requires StringLike<std::ranges::range_value_t<R>>
constexpr bool equal_to(I first, S last, R r) { constexpr bool equal_to(I first, S last, R r) {

View File

@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.26)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
add_executable(test_const_vector_constructor const_vector_constructor.test.cpp add_executable(test_const_vector_constructor const_vector_constructor.test.cpp
test_args.h
test_params.h) test_params.h)
target_link_libraries(test_const_vector_constructor const_container test_common) target_link_libraries(test_const_vector_constructor const_container test_common)
add_test(NAME "const_vector constructor" COMMAND test_const_vector_constructor) add_test(NAME "const_vector constructor" COMMAND test_const_vector_constructor)
@ -16,8 +17,3 @@ add_executable(test_const_vector_data_access const_vector_data_access.test.cpp
test_params.h) test_params.h)
target_link_libraries(test_const_vector_data_access const_container test_common) target_link_libraries(test_const_vector_data_access const_container test_common)
add_test(NAME "const_vector data access" COMMAND test_const_vector_data_access) add_test(NAME "const_vector data access" COMMAND test_const_vector_data_access)
add_executable(test_const_vector_data_augmentation const_vector_data_augmentation.test.cpp
test_params.h)
target_link_libraries(test_const_vector_data_augmentation const_container test_common)
add_test(NAME "const_vector data augmentation" COMMAND test_const_vector_data_augmentation)

View File

@ -1,248 +0,0 @@
#include <const_vector.hpp>
#include <test.hpp>
#include <vector>
#include <format>
#include "test_params.h"
#include <format>
#include <ranges>
#include <sstream>
template<std::ranges::range R, typename CharT>
struct std::formatter<R, CharT> {
template<typename ParseContext>
constexpr ParseContext::iterator parse(ParseContext& ctx) {
auto it = ctx.begin();
while (it != ctx.end() && *it != '}')
++it;
return it;
}
template<typename FmtContext>
constexpr FmtContext::iterator format(const R& range, FmtContext& ctx) const {
std::ostringstream out;
out << '[';
auto it = std::ranges::begin(range);
for (; it != std::next(std::ranges::begin(range), std::ranges::size(range) - 1); ++it) {
out << std::format("{}, ", *it);
}
out << std::format("{}]", *it);
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
}
};
template<typename CharT>
struct std::formatter<TestObj, CharT> {
template<typename ParseContext>
constexpr ParseContext::iterator parse(ParseContext &ctx)
{
auto it = ctx.begin();
while (it != ctx.end() && *it != '}')
++it;
return it;
}
template<typename FmtContext>
constexpr FmtContext::iterator format(const TestObj &obj, FmtContext &ctx) const
{
std::ostringstream out;
out << '(' << obj.x << ", '" << obj.c << "', \"" << obj.s << "\")";
return std::ranges::copy(std::move(out).str(), ctx.out()).out;
}
};
constexpr test_suite tests = define_tests("Data Augmentation")
("const_vector::clear()", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
cc::const_vector v(get_test_param<ctx, "arr">());
v.clear();
ASSERT(v.empty(), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::insert(const_iter pos, const T& value)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
cc::const_vector<T, c_arr_len(get_test_param<ctx, "arr">()) + 3> v(get_test_param<ctx, "arr">());
auto val_it = v.insert(std::next(v.begin()), get_test_param<ctx, "value">());
v.insert(val_it, *v.begin());
v.insert(v.end(), get_test_param<ctx, "value">());
ASSERT_THROWS((v.insert(v.end(), get_test_param<ctx, "value">())), std::length_error, ctx);
std::vector<T> comparable;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(comparable));
auto comparable_it = comparable.insert(std::next(comparable.begin()), get_test_param<ctx, "value">());
comparable.insert(comparable_it, *comparable.begin());
comparable.insert(comparable.end(), get_test_param<ctx, "value">());
ASSERT(ranges_equal(v, comparable), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::insert(const_iter pos, T&& value)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
auto value1 = make_copy(get_test_param<ctx, "value">());
auto value2 = make_copy(get_test_param<ctx, "arr">()[0]);
auto value3 = make_copy(get_test_param<ctx, "value">());
auto value4 = make_copy(get_test_param<ctx, "value">());
auto value1_comp = make_copy(get_test_param<ctx, "value">());
auto value2_comp = make_copy(get_test_param<ctx, "arr">()[0]);
auto value3_comp = make_copy(get_test_param<ctx, "value">());
cc::const_vector<T, c_arr_len(get_test_param<ctx, "arr">()) + 3> v(get_test_param<ctx, "arr">());
auto val_it = v.insert(std::next(v.begin()), force_move(value1));
v.insert(val_it, force_move(value2));
v.insert(v.end(), force_move(value3));
ASSERT_THROWS((v.insert(v.end(), force_move(value4))), std::length_error, ctx);
ASSERT_MSG((value4 == get_test_param<ctx, "value">()), "Value has been changed by failed move insert", ctx);
std::vector<T> comparable;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(comparable));
auto comparable_it = comparable.insert(std::next(comparable.begin()), force_move(value1_comp));
comparable.insert(comparable_it, force_move(value2_comp));
comparable.insert(comparable.end(), force_move(value3_comp));
ASSERT(ranges_equal(v, comparable), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::insert(const_iter pos, size_type count, const T &value)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
cc::const_vector<T, c_arr_len(get_test_param<ctx, "arr">()) + 9> v(get_test_param<ctx, "arr">());
auto it = v.insert(std::next(v.begin()), 3, get_test_param<ctx, "value">());
v.insert(it, 3, get_test_param<ctx, "arr">()[0]);
v.insert(v.end(), 3, get_test_param<ctx, "value">());
ASSERT_THROWS((v.insert(v.end(), 1, get_test_param<ctx, "value">())), std::length_error, ctx);
ASSERT_NOTHROW((v.insert(v.end(), 0, get_test_param<ctx, "value">())), std::length_error, ctx);
std::vector<T> comparable;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(comparable));
auto cit = comparable.insert(std::next(comparable.begin()), 3, get_test_param<ctx, "value">());
comparable.insert(cit, 3, get_test_param<ctx, "arr">()[0]);
comparable.insert(comparable.end(), 3, get_test_param<ctx, "value">());
ASSERT(ranges_equal(v, comparable), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::insert(const_iter pos, InputIt first, InputIt last)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
std::vector<T> src;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(src));
cc::const_vector<T, c_arr_len(get_test_param<ctx, "arr">()) * 3> v(get_test_param<ctx, "arr">());
auto it = v.insert(std::next(v.begin()), std::begin(get_test_param<ctx, "arr">()), std::end(get_test_param<ctx, "arr">()));
v.insert(it, src.begin(), std::next(src.begin() + src.size() / 2));
v.insert(v.end(), std::next(src.begin() + src.size() / 2), src.end());
ASSERT_THROWS((v.insert(v.end(), src.begin(), src.end())), std::length_error, ctx);
ASSERT_NOTHROW((v.insert(v.end(), src.begin(), src.begin())), std::length_error, ctx);
ASSERT(std::ranges::equal(src, get_test_param<ctx, "arr">()));
std::vector<T> comparable;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(comparable));
auto cit = comparable.insert(std::next(comparable.begin()), std::begin(get_test_param<ctx, "arr">()), std::end(get_test_param<ctx, "arr">()));
comparable.insert(cit, src.begin(), std::next(src.begin() + src.size() / 2));
comparable.insert(comparable.end(), std::next(src.begin() + src.size() / 2), src.end());
ASSERT(ranges_equal(v, comparable), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::insert(const_iter pos, std::initializer_list<T> values)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
cc::const_vector<T, get_test_param<ctx, "ilist">().size() * 4> v(get_test_param<ctx, "ilist">());
auto it = v.insert(std::next(v.begin()), get_test_param<ctx, "ilist">());
v.insert(it, get_test_param<ctx, "ilist">());
v.insert(v.end(), get_test_param<ctx, "ilist">());
ASSERT_THROWS((v.insert(v.end(), get_test_param<ctx, "ilist">())), std::length_error, ctx);
std::vector<T> comparable;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(comparable));
auto cit = comparable.insert(std::next(comparable.begin()), get_test_param<ctx, "ilist">());
comparable.insert(cit, get_test_param<ctx, "ilist">());
comparable.insert(comparable.end(), get_test_param<ctx, "ilist">());
ASSERT(ranges_equal(v, comparable), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::emplace(const_iterator pos, Args &&... args)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N, typename ctx>() constexpr {
cc::const_vector<T, get_test_param<ctx, "ilist">().size() * 4> v(get_test_param<ctx, "ilist">());
auto it = v.emplace();
ASSERT_THROWS((v.insert(v.end(), get_test_param<ctx, "ilist">())), std::length_error, ctx);
std::vector<T> comparable;
std::ranges::copy(get_test_param<ctx, "arr">(), std::back_inserter(comparable));
auto cit = comparable.insert(std::next(comparable.begin()), get_test_param<ctx, "ilist">());
comparable.insert(cit, get_test_param<ctx, "ilist">());
comparable.insert(comparable.end(), get_test_param<ctx, "ilist">());
ASSERT(ranges_equal(v, comparable), ctx);
return TEST_PASS();
}), 2, int, char, const char *, TestObj);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL);
int main() {
return tests.run();
}