Compare commits

...

5 commits

Author SHA1 Message Date
janis d6608aa6b4 fix generated view 2022-07-13 01:40:17 +01:00
janis 8b0ef87f17 removed old iterator that didnt do anything 2022-07-13 01:40:02 +01:00
janis bda4a77c86 if consteval fix for util::format 2022-07-13 01:39:48 +01:00
janis 8d56bc31ab transmute function 2022-07-05 13:32:35 +01:00
janis 734628e604 tests 2022-07-01 01:39:42 +01:00
5 changed files with 198 additions and 197 deletions

View file

@ -10,7 +10,15 @@ namespace util {
template <typename... Ts>
inline constexpr auto format(std::string_view fmt, Ts&&... args)
-> std::string {
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
#if defined(__cpp_if_consteval) && defined(doesnt_work_yet_in_clang_14)
if
consteval { return std::format(fmt, args...); }
else {
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
}
#else
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
#endif
}
template <typename T, typename Context>

View file

@ -180,151 +180,8 @@ public:
}
};
template <typename V, typename I = V *> struct BaseIterator {
using value_type = V;
using reference = V &;
using difference_type = std::ptrdiff_t;
I base_iter;
BaseIterator(const I &iter) : base_iter(iter) {}
BaseIterator(I &&iter) : base_iter(std::move(iter)) {}
};
template <typename V, typename I = V *>
struct InputOrOutputIterator : public BaseIterator<V, I> {
InputOrOutputIterator(const I &iter) : BaseIterator<V, I>(iter) {}
InputOrOutputIterator(I &&iter) : BaseIterator<V, I>(std::move(iter)) {}
auto constexpr operator*() const -> void {}
auto constexpr operator++(int) -> InputOrOutputIterator {
const auto ret = *this;
this->base_iter++;
return ret;
}
auto constexpr operator++() -> InputOrOutputIterator & {
this ++;
return *this;
}
};
template <typename V, typename I = V *>
struct InputIterator : public InputOrOutputIterator<V, I>,
public std::input_iterator_tag {
InputIterator(const I &iter) : BaseIterator<V, I>(iter) {}
InputIterator(I &&iter) : BaseIterator<V, I>(std::move(iter)) {}
auto constexpr operator*() const -> const V & { return *this->base_iter; }
};
template <typename V, typename I = V *>
struct OutputIterator : public InputOrOutputIterator<V, I>,
public std::output_iterator_tag {
OutputIterator(const I &iter) : BaseIterator<V, I>(iter) {}
OutputIterator(I &&iter) : BaseIterator<V, I>(std::move(iter)) {}
auto constexpr operator*() -> V & { return *this->base_iter; }
};
template <typename V, typename I = V *>
struct ForwardIterator : public InputIterator<V, I>,
public std::forward_iterator_tag {
ForwardIterator(const I &iter) : BaseIterator<V, I>(iter) {}
ForwardIterator(I &&iter) : BaseIterator<V, I>(std::move(iter)) {}
auto constexpr operator==(const ForwardIterator &rhs) const -> bool {
return this->base_iter == rhs.base_iter;
}
};
template <typename V, typename I = V *>
struct BidirectionalIterator : public ForwardIterator<V, I>,
public std::bidirectional_iterator_tag {
BidirectionalIterator(const I &iter) : BaseIterator<V, I>(iter) {}
BidirectionalIterator(I &&iter) : BaseIterator<V, I>(std::move(iter)) {}
auto constexpr operator--(int) -> BidirectionalIterator {
const auto ret = *this;
this->base_iter--;
return ret;
}
auto constexpr operator--() -> BidirectionalIterator & {
this --;
return *this;
}
};
template <typename V, typename I = V *>
struct RandomAccessIterator : public BidirectionalIterator<V, I>,
public std::random_access_iterator_tag {
using difference_type = typename BaseIterator<V, I>::difference_type;
RandomAccessIterator(const I &iter) : BaseIterator<V, I>(iter) {}
RandomAccessIterator(I &&iter) : BaseIterator<V, I>(std::move(iter)) {}
auto constexpr operator<=>(const RandomAccessIterator &rhs) const
-> std::strong_ordering {
return this->base_iter <=> rhs.base_iter;
}
auto constexpr operator-(const RandomAccessIterator &rhs) const
-> difference_type {
return this->base_iter - rhs.base_iter;
}
auto constexpr operator+(const difference_type &n) const
-> RandomAccessIterator {
return RandomAccessIterator(this->base_iter + n);
}
friend auto constexpr operator+(const difference_type &n,
const RandomAccessIterator &rhs)
-> RandomAccessIterator {
return rhs + n;
}
auto constexpr operator-(const difference_type &n) const
-> RandomAccessIterator {
return RandomAccessIterator(this->base_iter - n);
}
auto operator+=(const difference_type &n) -> RandomAccessIterator & {
*this = RandomAccessIterator(this->base_iter + n);
return *this;
}
auto operator-=(const difference_type &n) -> RandomAccessIterator & {
*this = RandomAccessIterator(this->base_iter - n);
return *this;
}
auto constexpr operator[](const difference_type &n) const -> const V & {
return this->base_iter[n];
}
auto operator[](const difference_type &n) -> V & {
return this->base_iter[n];
}
};
template <typename I>
using Iterator = std::conditional_t<
std::random_access_iterator<I>,
RandomAccessIterator<std::iter_value_t<I>, I>,
std::conditional_t<
std::bidirectional_iterator<I>,
BidirectionalIterator<std::iter_value_t<I>, I>,
std::conditional_t<
std::forward_iterator<I>, ForwardIterator<std::iter_value_t<I>, I>,
std::conditional_t<
std::output_iterator<I, decltype(*std::declval<I>())>,
OutputIterator<std::iter_value_t<I>, I>,
std::conditional_t<
std::input_iterator<I>,
InputIterator<std::iter_value_t<I>, I>,
std::conditional_t<
std::input_or_output_iterator<I>,
InputOrOutputIterator<std::iter_value_t<I>, I>,
RandomAccessIterator<I, I *>>>>>>>;
template <std::ranges::range R>
using RangeIterator = Iterator<std::ranges::iterator_t<R>>;
template <typename T, typename I>
concept iterator = std::same_as<typename iterator_t<I>::value_type, T>;
} // namespace util

View file

@ -17,11 +17,30 @@ template <std::invocable F> struct generated_iterator {
using difference_type = std::ptrdiff_t;
value_type value{};
F generator{};
F generator;
// TODO: make 1 constructor that generates a value, move/copy value in all
// other constructors
generated_iterator() = default;
generated_iterator(F gen) : generator(gen), value(gen()) {}
generated_iterator(F &&gen) : generator(std::move(gen)), value(gen()) {}
explicit generated_iterator(F &&gen)
: generator(std::move(gen)), value(gen()) {}
generated_iterator(const generated_iterator &other)
: generator(other.generator), value(other.value) {}
generated_iterator(generated_iterator &&other)
: generator(std::move(other.generator)), value(std::move(other.value)) {}
auto operator=(const generated_iterator &other) -> generated_iterator & {
generator = other.generator;
value = other.value;
return *this;
}
auto operator=(generated_iterator &&other) -> generated_iterator & {
generator = std::move(other.generator);
value = std::move(other.value);
return *this;
}
auto generate_new_value() -> void { value = generator(); }
@ -47,13 +66,14 @@ template <std::invocable F> struct generated_iterator {
template <std::invocable F>
class generated_view : rg::view_interface<generated_view<F>> {
F generator = {};
detail::generated_iterator<F> iter_{};
public:
constexpr generated_view() = default;
constexpr generated_view(F generator) : generator(std::move(generator)) {}
constexpr generated_view(F generator)
: iter_(detail::generated_iterator(std::move(generator))) {}
constexpr auto begin() const { return detail::generated_iterator(generator); }
constexpr auto begin() const { return iter_; }
constexpr auto end() const { return std::unreachable_sentinel; }
};

65
include/transmute.hpp Normal file
View file

@ -0,0 +1,65 @@
#pragma once
#include <utility>
namespace util {
template <typename T1, typename T2>
struct copy_const : std::type_identity<T2> {};
template <typename T1, typename T2>
struct copy_const<const T1, T2> : std::type_identity<const T2> {};
template <typename T1, typename T2>
using copy_const_t = typename copy_const<T1, T2>::type;
template <typename T1, typename T2>
struct copy_volatile : std::type_identity<T2> {};
template <typename T1, typename T2>
struct copy_volatile<volatile T1, T2> : std::type_identity<volatile T2> {};
template <typename T1, typename T2>
using copy_volatile_t = typename copy_volatile<T1, T2>::type;
template <typename T1, typename T2>
struct copy_cv : std::type_identity<copy_const_t<T1, copy_volatile_t<T1, T2>>> {
};
template <typename T1, typename T2>
using copy_cv_t = typename copy_cv<T1, T2>::type;
template <typename T1, typename T2>
struct copy_reference : std::type_identity<T2> {};
template <typename T1, typename T2>
struct copy_reference<T1 &, T2>
: std::type_identity<std::add_lvalue_reference_t<T2>> {};
template <typename T1, typename T2>
struct copy_reference<T1 &&, T2>
: std::type_identity<std::add_rvalue_reference_t<T2>> {};
template <typename T1, typename T2>
using copy_reference_t = typename copy_reference<T1, T2>::type;
template <typename T1, typename T2>
using copy_cvref_t = copy_reference_t<
T1, copy_reference_t<T2, copy_cv_t<std::remove_reference_t<T1>, T2>>>;
template <typename T2>
constexpr inline auto transmute(auto &&t1) -> copy_cvref_t<decltype(t1), T2> {
return std::forward<copy_cvref_t<decltype(t1), T2>>(
reinterpret_cast<copy_cvref_t<decltype(t1), T2>>(t1));
}
template <typename T2>
constexpr inline auto transmute(auto &t1) -> copy_cvref_t<decltype(t1), T2> {
return std::forward<copy_cvref_t<decltype(t1), T2>>(
reinterpret_cast<copy_cvref_t<decltype(t1), T2>>(t1));
}
template <typename T1, typename T2>
constexpr inline auto transmute(T1 t1) -> T2 {
return std::forward<T2>(reinterpret_cast<T2>(t1));
}
} // namespace util

View file

@ -4,7 +4,6 @@
#include "ranges/enumerate.hpp"
#include "ranges/first.hpp"
#include "ranges/generated.hpp"
#include "tagged_union.hpp"
#include <cstdlib>
#include <iostream>
#include <stdio.h>
@ -19,35 +18,78 @@
#include <vector>
using namespace std::string_view_literals;
using namespace util::bitflag_operators;
enum class E {
A = 0x1,
B = 0x10,
C = 0x100,
D = 0x1000,
};
#include "iterator.hpp"
int main(int argc, const char *argv[]) {
printf("Hello, Alloy!\n");
auto test_iterator_t() {
int *ptr = nullptr;
int arr[5] = {0, 1, 2, 3, 4};
using int_ptr_iterator_t = util::iterator_t<int *>;
auto a = int_ptr_iterator_t(arr);
const auto a = E::A;
const auto ab = E::A | E::B;
const auto all = E::A | E::B | E::C | E::D;
const auto three = a[3];
a += 2;
*a = 6;
auto vec = std::vector<int>({1, 2, 3, 4, 5});
for (auto &&e : arr) {
util::println("{}", e);
}
}
auto range = vec | std::views::filter([](auto &i) { return i % 2; });
auto infinite_range = util::views::from([] {return 1;}) | std::views::take(5);
auto test_enumerate_view() {
auto enumerated = util::views::from([] { return 1; }) |
util::views::enumerate | std::views::take(10);
auto map =
vec | util::views::enumerate | util::views::collect<std::map<int, int>>;
auto b = std::ranges::begin(enumerated);
for (auto &&[i, e] : map) {
for (auto &&[i, e] : enumerated) {
util::println("[{}] {}", i, e);
}
auto random = util::views::from([] {
for (auto &&[i, e] : enumerated | util::views::enumerate) {
util::println("[{}] {}", i, e.value);
}
auto transformed_enumerate =
util::views::from([] { return 1; }) |
std::views::transform([](auto &&i) { return i + 1; }) |
util::views::enumerate | std::views::take(10);
for (auto &&[i, e] : transformed_enumerate) {
util::println("[{}] {}", i, e);
}
}
auto test_generated_view() {
{
const auto view = util::views::from([] { return 's'; });
auto it = std::ranges::begin(view);
util::assert_eq(*it, *it);
util::assert_eq(*it, 's');
}
{
auto count = 0;
const auto view = util::views::from([&] { return count++; });
auto it = std::ranges::begin(view);
util::assert_eq(*it, *it);
util::assert_ne(*it++, *it++);
util::assert_ne(*it + 1, *++it);
}
}
auto test_collect() {
auto vec = std::vector<int>({1, 2, 3, 4, 5});
auto range = vec | std::views::filter([](auto &i) { return i % 2; });
const auto set = util::collect<std::set<int>>(range);
}
auto test_first() {
const auto random =
util::views::from([] {
return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY"
[std::rand() %
std::strlen(
@ -55,20 +97,29 @@ int main(int argc, const char *argv[]) {
}) |
std::views::take(10) | util::views::collect<std::string>;
auto first = random | util::views::first;
const auto first = random | util::views::first;
util::println("{}", first);
}
util::println("{}", first);
util::println("{}", random);
auto test_assert_no_fail() {
util::assert_ne("asdf"sv, "nsdf"sv);
util::assert_eq(1, 1);
util::assert_eq(1 == 1, true);
util::assert_eq(0, false);
}
for (auto&& i : infinite_range) {
util::print("{}\n", i);
}
auto test_panic() { util::panic("asdf {}", 42); }
const auto set = util::collect<std::set<int>>(range);
int main(int argc, const char *argv[]) {
printf("Hello, Alloy!\n");
test_iterator_t();
test_enumerate_view();
test_collect();
test_generated_view();
test_first();
test_assert_no_fail();
util::print("hello {}\n", "world");
util::assert_ne("asdf"sv, "nsdf"sv);
util::panic("asdf {}", 42);
return 1;
}