Compare commits

...

7 Commits

3 changed files with 165 additions and 31 deletions

View File

@ -358,9 +358,8 @@ namespace cc {
template<typename T, std::size_t N>
constexpr void const_vector<T, N>::assign(std::initializer_list<value_type> values)
{
auto values_size = std::distance(values.begin(), values.end());
if (values_size > N) throw std::invalid_argument("Initializer list in assign has more elements than size" + std::to_string(values_size) + ">=" + std::to_string(N));
_size = values_size;
if (values.size() > N) throw std::invalid_argument("Initializer list in assign has more elements than size" + std::to_string(values_size) + ">=" + std::to_string(N));
_size = values.size();
std::copy(values.begin(), values.end(), _arr);
}

View File

@ -29,37 +29,74 @@
#define TEST_PASS_MSG_TYPE(msg, type_hint) ret_val_s { "", ReturnCode::PASSED, msg, to_type_hint_str::value<type_hint> }
#define TEST_SKIP_TYPE(type_hint) ret_val_s { "", ReturnCode::SKIPPED, nullptr, to_type_hint_str::value<type_hint> }
#define ASSERT_TYPE(condition, type) ASSERT_TYPE_MSG(condition, #condition "" _LOCATION, type)
#define ASSERT_TYPE_MSG(condition, msg, type) { if (!(condition)) return TEST_FAIL_TYPE(msg, type); } static_assert(true, "")
#define ASSERT_TYPE_ALL_EQ(first, last, eq, type) ASSERT_TYPE_MSG(std::all_of(first, last, all_eq_arr_elem_test_func(eq)), "Not all elements in (" #first ", " #last ") equal " #eq "" _LOCATION, type)
#define ASSERT_TYPE_C_ARR_EQ(first, last, eq, type) ASSERT_TYPE_MSG(std::equal(first, last, eq, all_eq_arr_arr_test_func<decltype(eq)>()), "Elements in (" #first ", " #last ") and " #eq " differ" _LOCATION, type)
#define ASSERT_TYPE_ITER_EQ(first, last, eq, type) ASSERT_TYPE_MSG(std::equal(first, last, (eq).begin(), all_eq_arr_arr_test_func<std::iterator_traits<decltype(eq)::iterator>::value_type>()), "Elements in (" #first ", " #last ") and " #eq " differ" _LOCATION, type)
#define TEST_FAIL_TYPE_NUM(msg, type_hint, num) ret_val_s { "", ReturnCode::FAILED, msg, to_type_hint_str::value<type_hint>, num }
#define TEST_PASS_TYPE_NUM(type_hint, num) ret_val_s { "", ReturnCode::PASSED, nullptr, to_type_hint_str::value<type_hint>, num }
#define TEST_PASS_MSG_TYPE_NUM(msg, type_hint, num) ret_val_s { "", ReturnCode::PASSED, msg, to_type_hint_str::value<type_hint>, num }
#define TEST_SKIP_TYPE_NUM(type_hint, num) ret_val_s { "", ReturnCode::SKIPPED, nullptr, to_type_hint_str::value<type_hint>, num }
#define ASSERT_TYPE_NUM(condition, type, num) ASSERT_TYPE_NUM_MSG(condition, #condition "" _LOCATION, type, num)
#define ASSERT_TYPE_NUM_MSG(condition, msg, type, num) { if (!(condition)) return TEST_FAIL_TYPE_NUM(msg, type, num); } static_assert(true, "")
#define ASSERT_TYPE_NUM_ALL_EQ(first, last, eq, type, num) ASSERT_TYPE_NUM_MSG(all_eq_to(first, last, eq), "Not all elements in (" #first ", " #last ") equal " #eq "" _LOCATION, type, num)
#define ASSERT_TYPE_NUM_C_ARR_EQ(first, last, eq, type, num) ASSERT_TYPE_NUM_MSG(equal_to(first, last, eq), "Elements in (" #first ", " #last ") and " #eq " differ" _LOCATION, type, num)
#define ASSERT_TYPE(condition, type) ASSERT_TYPE_NUM(condition, type, -1ULL)
#define ASSERT_TYPE_MSG(condition, msg, type) ASSERT_TYPE_NUM_MSG(condition, msg, type -1ULL)
#define ASSERT_TYPE_ALL_EQ(first, last, eq, type) ASSERT_TYPE_NUM_ALL_EQ(first, last, eq, type, -1ULL)
#define ASSERT_TYPE_C_ARR_EQ(first, last, eq, type) ASSERT_TYPE_NUM_C_ARR_EQ(first, last, eq, type, -1ULL)
#define ASSERT(condition) ASSERT_TYPE(condition, std::nullptr_t)
#define ASSERT_MSG(condition, msg) ASSERT_TYPE_MSG(condition, msg, std::nullptr_t)
#define ASSERT_ALL_EQ(first, last, eq) ASSERT_TYPE_ALL_EQ(first, last, eq, std::nullptr_t)
#define ASSERT_C_ARR_EQ(first, last, eq) ASSERT_TYPE_C_ARR_EQ(first, last, eq, std::nullptr_t)
#define ASSERT_ITER_EQ(first, last, eq) ASSERT_TYPE_ITER_EQ(first, last, eq, std::nullptr_t)
#define ASSERT_TYPE_THROWS(operation, exception_type, type) if not consteval { try { operation; ASSERT_TYPE_MSG(false, #operation " did not throw " #exception_type _LOCATION, type); } catch (exception_type &e) {} } static_assert(true, "")
#define ASSERT_TYPE_NUM_THROWS(operation, exception_type, type, num) if not consteval { try { operation; ASSERT_TYPE_NUM_MSG(false, #operation " did not throw " #exception_type _LOCATION, type, num); } catch (exception_type &e) {} } static_assert(true, "")
#define ASSERT_TYPE_THROWS(operation, exception_type, type) ASSERT_TYPE_NUM_THROWS(operation, exception_type, type, -1ULL)
#define ASSERT_THROWS(operation, exception_type) ASSERT_TYPE_THROWS(operation, exception_type, std::nullptr_t)
template<typename T>
constexpr auto all_eq_arr_elem_test_func(T&& eq) {
return [=] (auto&& e) constexpr { return e == eq; };
}
template<const char *>
constexpr auto all_eq_arr_elem_test_func(const char* eq) {
return [=] (auto&& e) constexpr { return std::string_view(e) == eq; };
concept StringLike = std::is_convertible_v<T, std::string_view>;
template<std::input_iterator I, std::sentinel_for<I> S, StringLike T>
constexpr bool all_eq_to(I first, S last, T t) {
auto r1 = std::ranges::subrange(first, last);
auto r2 = std::ranges::views::repeat(std::string_view(t), std::ranges::distance(first, last));
return std::ranges::equal(r1, r2);
}
template<typename T>
constexpr auto all_eq_arr_arr_test_func() {
return [] (auto&& a, auto&& b) constexpr { return a == b; };
template<std::input_iterator I, std::sentinel_for<I> S, typename T>
constexpr bool all_eq_to(I first, S last, T t) {
auto r1 = std::ranges::subrange(first, last);
auto r2 = std::ranges::views::repeat(t, std::ranges::distance(first, last));
return std::ranges::equal(r1, r2);
}
template<const char *>
constexpr auto all_eq_arr_arr_test_func() {
return [] (auto&& a, auto&& b) constexpr { return std::string_view(a) == b; };
template<std::input_iterator I, std::sentinel_for<I> S, std::ranges::range R>
requires StringLike<std::ranges::range_value_t<R>>
constexpr bool equal_to(I first, S last, R r) {
auto r1 = std::ranges::subrange(first, last);
auto r2 = r | std::ranges::views::transform([](auto&& e) constexpr { return std::string_view(e); });
return std::ranges::equal(r1, r2);
}
template<std::input_iterator I, std::sentinel_for<I> S, std::ranges::range R>
constexpr bool equal_to(I first, S last, R r) {
return std::ranges::equal(std::ranges::subrange(first, last), r);
}
template<std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2>
requires StringLike<typename std::iterator_traits<I2>::value_type>
constexpr bool equal_to(I1 first1, S1 last1, I2 first2) {
auto r1 = std::ranges::subrange(first1, last1);
auto r2 = std::ranges::subrange(first2, std::next(first2, std::distance(first1, last1)))
| std::ranges::views::transform([](auto&& e) constexpr { return std::string_view(e); });
return std::ranges::equal(r1, r2);
}
template<std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2>
constexpr bool equal_to(I1 first1, S1 last1, I2 first2) {
auto r1 = std::ranges::subrange(first1, last1);
auto r2 = std::ranges::subrange(first2, std::next(first2, std::distance(first1, last1)));
return std::ranges::equal(r1, r2);
}
enum class EvalFlag { RUNTIME, CONSTEVAL, RUNTIME_CONSTEVAL };
@ -89,6 +126,7 @@ struct ret_val_s {
ReturnCode val = ReturnCode::FAILED;
const char *msg = "";
const char *type_hint = nullptr;
std::size_t param_nr = -1;
};
template<std::size_t Nr>
@ -183,6 +221,9 @@ class test_suite {
if (ret.type_hint != nullptr) {
std::cout << "\n\t" << "with type '" << ret.type_hint << "'";
}
if (ret.param_nr != -1) {
std::cout << "\n\t" << "with parameter param_nr: " << ret.param_nr;
}
std::cout << std::endl;
ret_vals[i][0] = ret.val;
@ -197,6 +238,9 @@ class test_suite {
if (ret.type_hint != nullptr) {
std::cout << "\n\t" << "with type '" << ret.type_hint << "'";
}
if (ret.param_nr != -1) {
std::cout << "\n\t" << "with parameter param_nr: " << ret.param_nr;
}
std::cout << std::endl;
ret_vals[i][1] = ret.val;
@ -292,14 +336,41 @@ constexpr auto _repeat_for_types(auto f) {
return rets;
}
template <std::size_t _N, typename ...Ts, std::size_t N = _N - 1>
constexpr auto _repeat_for_types_n(auto f) {
std::array rets = {
[&]<typename T, std::size_t ...Ns>(std::index_sequence<Ns...>) constexpr {
return std::array { f.template operator()<T, Ns+1>()... };
}.template operator()<Ts>(std::make_index_sequence<N>())...
};
// Clion does not accept this as a constant expression
// even though it compiles and works as intended
//return rets | std::ranges::views::join;
std::array<ret_val_s, sizeof...(Ts) * N> arr;
auto arr_it = std::begin(arr);
for (auto&& rp : rets) {
for (ret_val_s& r : rp) {
*(arr_it++) = r;
}
}
return arr;
}
#define REPEAT_FOR_TYPES(func, ...) { \
auto r = _repeat_for_types<__VA_ARGS__>(func); \
auto it = std::ranges::find_if(r, [](auto&& e) { return e.val == ReturnCode::FAILED; }); \
auto it = std::ranges::find_if(r, [](auto&& e) constexpr { return e.val == ReturnCode::FAILED; }); \
if (it != std::ranges::end(r)) { \
return *it; \
} \
}
} static_assert(true, "")
#define REPEAT_FOR_TYPES_N(func, N, ...) { \
auto r = _repeat_for_types_n<N, __VA_ARGS__>(func); \
auto it = std::ranges::find_if(r, [](auto&& e) constexpr { return e.val == ReturnCode::FAILED; }); \
if (it != std::ranges::end(r)) { \
return *it; \
} \
} static_assert(true, "")
#define CREATE_FROM_IL(type, il, len) \
([]<std::size_t N, typename ArgType>(std::initializer_list<ArgType> args) { \

View File

@ -3,14 +3,21 @@
#include <const_vector.hpp>
#include "test.hpp"
#include "test_args.h"
#define ASSERT_TYPE_ALL_VEC_EQ(vec, eq, type) ASSERT_ALL_EQ((vec).begin(), (vec).end(), eq)
#define ASSERT_TYPE_RANGE_VEC_EQ(vec, startI, endI, eq, type) ASSERT_ALL_EQ(((vec).data() + startI), ((vec).data() + endI), eq)
#define ASSERT_TYPE_VEC_ARR_EQ(vec, eq, type) ASSERT_C_ARR_EQ((vec).data(), (vec).data() + (vec).size(), std::begin(eq))
#define ASSERT_TYPE_VEC_EQ(vec1, vec2, type) ASSERT_C_ARR_EQ((vec1).data(), (vec1).data() + (vec1).size(), (vec2).data())
#define ASSERT_TYPE_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, type) ASSERT_C_ARR_EQ(((vec).begin() + startI), ((vec).begin() + endI), std::begin(eq))
#include <vector>
#define ASSERT_TYPE_NUM_ALL_VEC_EQ(vec, eq, type, num) ASSERT_TYPE_NUM_ALL_EQ((vec).begin(), (vec).end(), eq, type, num)
#define ASSERT_TYPE_NUM_RANGE_VEC_EQ(vec, startI, endI, eq, type, num) ASSERT_TYPE_NUM_ALL_EQ(((vec).data() + startI), ((vec).data() + endI), eq, type, num)
#define ASSERT_TYPE_NUM_VEC_ARR_EQ(vec, eq, type, num) ASSERT_TYPE_NUM_C_ARR_EQ((vec).data(), (vec).data() + (vec).size(), std::begin(eq), type, num)
#define ASSERT_TYPE_NUM_VEC_EQ(vec1, vec2, type, num) ASSERT_TYPE_NUM_C_ARR_EQ((vec1).data(), (vec1).data() + (vec1).size(), (vec2).data(), type, num)
#define ASSERT_TYPE_NUM_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, type, num) ASSERT_TYPE_NUM_C_ARR_EQ(((vec).begin() + startI), ((vec).begin() + endI), std::begin(eq), type, num)
#define ASSERT_TYPE_ALL_VEC_EQ(vec, eq, type) ASSERT_TYPE_ALL_EQ((vec).begin(), (vec).end(), eq, type)
#define ASSERT_TYPE_RANGE_VEC_EQ(vec, startI, endI, eq, type) ASSERT_TYPE_ALL_EQ(((vec).data() + startI), ((vec).data() + endI), eq, type)
#define ASSERT_TYPE_VEC_ARR_EQ(vec, eq, type) ASSERT_TYPE_C_ARR_EQ((vec).data(), (vec).data() + (vec).size(), std::begin(eq), type)
#define ASSERT_TYPE_VEC_EQ(vec1, vec2, type) ASSERT_TYPE_C_ARR_EQ((vec1).data(), (vec1).data() + (vec1).size(), (vec2).data(), type)
#define ASSERT_TYPE_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, type) ASSERT_TYPE_C_ARR_EQ(((vec).begin() + startI), ((vec).begin() + endI), std::begin(eq), type)
#define ASSERT_ALL_VEC_EQ(vec, eq) ASSERT_TYPE_ALL_VEC_EQ(vec, eq, std::nullptr_t)
#define ASSERT_RANGE_VEC_EQ(vec, startI, endI, eq) ASSERT_TYPE_RANGE_VEC_EQ(vec, startI, endI, eq, std::nullptr_t)
@ -18,6 +25,7 @@
#define ASSERT_VEC_EQ(vec1, vec2) ASSERT_TYPE_VEC_EQ(vec1, vec2, std::nullptr_t)
#define ASSERT_RANGE_VEC_ARR_EQ(vec, startI, endI, eq) ASSERT_TYPE_RANGE_VEC_ARR_EQ(vec, startI, endI, eq, std::nullptr_t)
constexpr test_suite tests = define_tests("Tests")
("const_vector()", []() constexpr {
@ -1142,10 +1150,65 @@ constexpr test_suite tests = define_tests("Tests")
ASSERT_TYPE_ALL_VEC_EQ(v1, test_defs::get<T>::template value<1>(), T);
return TEST_PASS();
}), int, char, const char*, TestStruct)
}), int, char, const char*, TestStruct);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::assign(InputIt first, InputIt last)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N>() constexpr {
cc::const_vector<T, test_defs::get<T>::template arr_len<N>()> v1;
cc::const_vector<T, test_defs::get<T>::template il_len<N>()> v2;
cc::const_vector<T, test_defs::get<T>::template il_len<N>()> v3;
cc::const_vector<T, test_defs::get<T>::template arr_len<N>() - 1> v4;
std::vector<T> container = test_defs::get<T>::template i_list<N>;
v1.assign(std::begin(test_defs::get<T>::template arr<N>), std::end(test_defs::get<T>::template arr<N>));
v2.assign(container.begin(), container.end());
v3.assign(container.begin(), std::next(container.begin(), test_defs::get<T>::template il_len<N>() / 2));
ASSERT_TYPE_NUM_THROWS(
(v4.assign(std::begin(test_defs::get<T>::template arr<N>),
std::end(test_defs::get<T>::template arr<N>))), std::invalid_argument, T, N);
ASSERT_TYPE_NUM_VEC_ARR_EQ(v1, test_defs::get<T>::template arr<N>, T, N);
ASSERT_TYPE_NUM(v1.size() == test_defs::get<T>::template arr_len<N>(), T, N);
ASSERT_TYPE_NUM_VEC_ARR_EQ(v2, container, T, N);
ASSERT_TYPE_NUM(v2.size() == container.size(), T, N);
ASSERT_TYPE_NUM_VEC_ARR_EQ(v3, container, T, N);
ASSERT_TYPE_NUM(v3.size() == container.size() / 2, T, N);
return TEST_PASS();
}), 3, int, char, const char *, TestStruct);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
("const_vector::assign(std::initializer_list<value_type> values)", []() constexpr {
REPEAT_FOR_TYPES_N(([]<typename T, std::size_t N>() constexpr {
cc::const_vector<T, test_defs::get<T>::template il_len<N>()> v1;
cc::const_vector<T, test_defs::get<T>::template il_len<N>() - 1> v2;
v1.assign(test_defs::get<T>::template i_list<N>);
ASSERT_TYPE_NUM_VEC_ARR_EQ(v1, test_defs::get<T>::template i_list<N>, T, N);
ASSERT_TYPE_NUM(v1.size() == test_defs::get<T>::template il_len<N>(), T, N);
ASSERT_TYPE_NUM_THROWS(v2.assign(test_defs::get<T>::template i_list<N>), std::invalid_argument, T, N);
return TEST_PASS();
}), 2, int, char, const char *, TestStruct);
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)
/*("const_vector", []() constexpr {
return TEST_PASS();
}, EvalFlag::RUNTIME_CONSTEVAL)*/
/*("const_vector(const_vector&& other)", []() constexpr {
return TEST_PASS();
@ -1155,4 +1218,5 @@ constexpr test_suite tests = define_tests("Tests")
int main() {
return tests.run();
}
#pragma clang diagnostic pop