Created
October 29, 2020 11:10
-
-
Save rmu75/428c302a7bacc4b5e6ca622a70bfdeff to your computer and use it in GitHub Desktop.
C++ unique frozen sets proof of concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
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
That's smart!