Compare commits
No commits in common. "d6608aa6b4cc686974de66c612fb4b0a1dad6526" and "b872cc940bbc7955f819ce55f022e236677ca004" have entirely different histories.
d6608aa6b4
...
b872cc940b
|
@ -10,15 +10,7 @@ namespace util {
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
inline constexpr auto format(std::string_view fmt, Ts&&... args)
|
inline constexpr auto format(std::string_view fmt, Ts&&... args)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
#if defined(__cpp_if_consteval) && defined(doesnt_work_yet_in_clang_14)
|
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
|
||||||
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>
|
template <typename T, typename Context>
|
||||||
|
|
|
@ -180,8 +180,151 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename I>
|
template <typename V, typename I = V *> struct BaseIterator {
|
||||||
concept iterator = std::same_as<typename iterator_t<I>::value_type, T>;
|
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>>;
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
|
|
|
@ -17,30 +17,11 @@ template <std::invocable F> struct generated_iterator {
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
value_type value{};
|
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() = default;
|
||||||
explicit generated_iterator(F &&gen)
|
generated_iterator(F gen) : generator(gen), value(gen()) {}
|
||||||
: generator(std::move(gen)), value(gen()) {}
|
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(); }
|
auto generate_new_value() -> void { value = generator(); }
|
||||||
|
|
||||||
|
@ -66,14 +47,13 @@ template <std::invocable F> struct generated_iterator {
|
||||||
|
|
||||||
template <std::invocable F>
|
template <std::invocable F>
|
||||||
class generated_view : rg::view_interface<generated_view<F>> {
|
class generated_view : rg::view_interface<generated_view<F>> {
|
||||||
detail::generated_iterator<F> iter_{};
|
F generator = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr generated_view() = default;
|
constexpr generated_view() = default;
|
||||||
constexpr generated_view(F generator)
|
constexpr generated_view(F generator) : generator(std::move(generator)) {}
|
||||||
: iter_(detail::generated_iterator(std::move(generator))) {}
|
|
||||||
|
|
||||||
constexpr auto begin() const { return iter_; }
|
constexpr auto begin() const { return detail::generated_iterator(generator); }
|
||||||
constexpr auto end() const { return std::unreachable_sentinel; }
|
constexpr auto end() const { return std::unreachable_sentinel; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
#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
|
|
141
src/main.cc
141
src/main.cc
|
@ -4,6 +4,7 @@
|
||||||
#include "ranges/enumerate.hpp"
|
#include "ranges/enumerate.hpp"
|
||||||
#include "ranges/first.hpp"
|
#include "ranges/first.hpp"
|
||||||
#include "ranges/generated.hpp"
|
#include "ranges/generated.hpp"
|
||||||
|
#include "tagged_union.hpp"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -18,108 +19,56 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace std::string_view_literals;
|
using namespace std::string_view_literals;
|
||||||
|
using namespace util::bitflag_operators;
|
||||||
|
|
||||||
#include "iterator.hpp"
|
enum class E {
|
||||||
|
A = 0x1,
|
||||||
auto test_iterator_t() {
|
B = 0x10,
|
||||||
int *ptr = nullptr;
|
C = 0x100,
|
||||||
int arr[5] = {0, 1, 2, 3, 4};
|
D = 0x1000,
|
||||||
using int_ptr_iterator_t = util::iterator_t<int *>;
|
};
|
||||||
auto a = int_ptr_iterator_t(arr);
|
|
||||||
|
|
||||||
const auto three = a[3];
|
|
||||||
a += 2;
|
|
||||||
*a = 6;
|
|
||||||
|
|
||||||
for (auto &&e : arr) {
|
|
||||||
util::println("{}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto test_enumerate_view() {
|
|
||||||
auto enumerated = util::views::from([] { return 1; }) |
|
|
||||||
util::views::enumerate | std::views::take(10);
|
|
||||||
|
|
||||||
auto b = std::ranges::begin(enumerated);
|
|
||||||
|
|
||||||
for (auto &&[i, e] : enumerated) {
|
|
||||||
util::println("[{}] {}", i, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY")];
|
|
||||||
}) |
|
|
||||||
std::views::take(10) | util::views::collect<std::string>;
|
|
||||||
|
|
||||||
const auto first = random | util::views::first;
|
|
||||||
util::println("{}", first);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto test_panic() { util::panic("asdf {}", 42); }
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
printf("Hello, Alloy!\n");
|
printf("Hello, Alloy!\n");
|
||||||
|
|
||||||
test_iterator_t();
|
const auto a = E::A;
|
||||||
test_enumerate_view();
|
const auto ab = E::A | E::B;
|
||||||
test_collect();
|
const auto all = E::A | E::B | E::C | E::D;
|
||||||
test_generated_view();
|
|
||||||
test_first();
|
auto vec = std::vector<int>({1, 2, 3, 4, 5});
|
||||||
test_assert_no_fail();
|
|
||||||
|
auto range = vec | std::views::filter([](auto &i) { return i % 2; });
|
||||||
|
auto infinite_range = util::views::from([] {return 1;}) | std::views::take(5);
|
||||||
|
|
||||||
|
auto map =
|
||||||
|
vec | util::views::enumerate | util::views::collect<std::map<int, int>>;
|
||||||
|
|
||||||
|
for (auto &&[i, e] : map) {
|
||||||
|
util::println("[{}] {}", i, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto random = util::views::from([] {
|
||||||
|
return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY"
|
||||||
|
[std::rand() %
|
||||||
|
std::strlen(
|
||||||
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY")];
|
||||||
|
}) |
|
||||||
|
std::views::take(10) | util::views::collect<std::string>;
|
||||||
|
|
||||||
|
auto first = random | util::views::first;
|
||||||
|
|
||||||
|
util::println("{}", first);
|
||||||
|
util::println("{}", random);
|
||||||
|
|
||||||
|
for (auto&& i : infinite_range) {
|
||||||
|
util::print("{}\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto set = util::collect<std::set<int>>(range);
|
||||||
|
|
||||||
util::print("hello {}\n", "world");
|
util::print("hello {}\n", "world");
|
||||||
|
|
||||||
|
util::assert_ne("asdf"sv, "nsdf"sv);
|
||||||
|
util::panic("asdf {}", 42);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
Loading…
Reference in a new issue