Skip to content

Instantly share code, notes, and snippets.

@rmu75
Created October 29, 2020 11:10
Show Gist options
  • Save rmu75/428c302a7bacc4b5e6ca622a70bfdeff to your computer and use it in GitHub Desktop.
Save rmu75/428c302a7bacc4b5e6ca622a70bfdeff to your computer and use it in GitHub Desktop.
C++ unique frozen sets proof of concept
#include <algorithm>
#include <iostream>
#include <type_traits>
#include <utility>
#include "frozen/set.h"
#include "frozen/string.h"
template<typename... Arrs>
constexpr auto concat(const Arrs&... arrs) {
std::size_t cur = 0;
std::array<std::common_type_t<typename Arrs::value_type...>, (std::tuple_size_v<Arrs> + ...)> result;
([&](const auto& arr) {
for (const auto& elem : arr) {
result[cur++] = elem;
}
}(arrs), ...);
return result;
}
template<typename _ForwardIterator>
constexpr
_ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last)
{
// Do the real copy work.
_ForwardIterator __dest = __first;
++__first;
while (++__first != __last)
if (*__dest != *__first)
*++__dest = std::move(*__first);
return ++__dest;
}
template<typename _ForwardIterator>
constexpr
size_t count_unique(_ForwardIterator __first, _ForwardIterator __last)
{
// Do the real copy work.
_ForwardIterator __dest = __first;
size_t res = 1;
++__first;
while (++__first != __last)
if (*__dest != *__first) {
*++__dest = std::move(*__first);
++res;
}
return res;
}
template <typename T, std::size_t N>
constexpr frozen::bits::carray<T,N> unique(frozen::bits::carray<T, N> const& array)
{
frozen::bits::carray<T, N> res = array;
auto end = unique(res.begin(), res.end());
return res;
}
constexpr size_t count_unique(frozen::bits::carray<T, N> const& array)
{
frozen::bits::carray<T, N> res = array;
return count_unique(res.begin(), res.end());
}
int main() {
constexpr std::array<const char*, 8> a1{"a", "b", "D", "d", "e", "E", "f", "G"};
constexpr std::array<const char*, 5> a2{"A", "b", "c", "D", "d"};
constexpr std::array<const char*, 5> a3{"B", "d", "E", "f", "g"};
for (const auto& elem : concat(a1, a2, a3)) {
std::cout << elem << " ";
}
std::cout << std::endl;
constexpr auto a = concat(a1, a2, a3);
constexpr auto sz = a.size();
std::cout << a.size() << std::endl;
std::less<frozen::string> less_than;
constexpr auto ca = frozen::bits::quicksort(frozen::bits::carray<frozen::string, a.size()>(a), less_than);
constexpr auto sca = count_unique(ca);
std::cout << "unique: " << sca << std::endl;
constexpr auto u = unique(ca);
frozen::bits::carray<frozen::string, sca> e(u);
//constexpr auto s = frozen::make_set<double>((const double (&)[a.size()])(a));
constexpr auto s = frozen::set<frozen::string, a.size()>(ca);
for (const auto& elem: s) {
std::cout << elem.data() << " ";
}
std::cout << std::endl;
std::cout << count_unique(ca) << std::endl;
for (const auto& elem: ca) {
std::cout << elem.data() << " ";
}
std::cout << std::endl;
for (const auto& elem: e) {
std::cout << elem.data() << " ";
}
std::cout << std::endl;
}
diff --git a/include/frozen/bits/basic_types.h b/include/frozen/bits/basic_types.h
index 9814bac..742ad5f 100644
--- a/include/frozen/bits/basic_types.h
+++ b/include/frozen/bits/basic_types.h
@@ -121,6 +121,16 @@ public:
// clang & gcc doesn't recognize init.size() as a constexpr
// static_assert(init.size() >= N, "Cannot initialize a carray with an smaller initializer list");
}
+ constexpr carray(const std::array<T, N> &arr)
+ : carray(arr.begin(), std::make_index_sequence<N>())
+ {
+ }
+
+ template <typename U>
+ constexpr carray(U &arr)
+ : carray(arr.begin(), std::make_index_sequence<N>())
+ {
+ }
// Iterators
constexpr iterator begin() noexcept { return data_; }
diff --git a/include/frozen/string.h b/include/frozen/string.h
index c43524f..a921ebf 100644
--- a/include/frozen/string.h
+++ b/include/frozen/string.h
@@ -37,13 +37,18 @@ class basic_string {
chr_t const *data_;
std::size_t size_;
+ size_t constexpr strlen(const char* str)
+ {
+ return *str ? 1 + strlen(str + 1) : 0;
+ }
+
public:
template <std::size_t N>
constexpr basic_string(chr_t const (&data)[N])
: data_(data), size_(N - 1) {}
constexpr basic_string(chr_t const *data, std::size_t size)
: data_(data), size_(size) {}
-
+ constexpr basic_string(chr_t const *data) : data_(data), size_(strlen(data)) {}
constexpr basic_string(const basic_string &) noexcept = default;
constexpr basic_string &operator=(const basic_string &) noexcept = default;
@serge-sans-paille
Copy link

That's smart!

@rmu75
Copy link
Author

rmu75 commented Oct 30, 2020

Thanks.

unique is more or less identical to std::unique, but in my tests i can't access the return value in a constant expression, hence the need for "count_unique".

I will try to come up with a PR along this concept in the next 1-2 weeks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment