Skip to content

Commit

Permalink
Example implementation of enumerate
Browse files Browse the repository at this point in the history
  • Loading branch information
willdealtry committed Feb 29, 2024
1 parent 150e30d commit 90770ed
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 2 deletions.
4 changes: 2 additions & 2 deletions cpp/arcticdb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ set(arcticdb_srcs
version/version_utils.cpp
version/symbol_list.cpp
version/version_map_batch_methods.cpp
)
util/enumerate.hpp)

if(${ARCTICDB_INCLUDE_ROCKSDB})
list (APPEND arcticdb_srcs
Expand Down Expand Up @@ -815,7 +815,7 @@ if(${TEST})
version/test/test_sorting_info_state_machine.cpp
version/test/version_map_model.hpp
storage/test/common.hpp
)
util/test/test_enumerate.cpp)

set(EXECUTABLE_PERMS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # 755

Expand Down
114 changes: 114 additions & 0 deletions cpp/arcticdb/util/enumerate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#pragma once

// An internal implementation of folly's enumerate: https://github.com/facebook/folly/blob/main/folly/container/Enumerate.h

#include <iterator>
#include <memory>

#include <arcticdb/util/preprocess.hpp>

namespace arcticdb {

namespace detail {

template <class T>
struct MakeConst {
using type = const T;
};
template <class T>
struct MakeConst<T&> {
using type = const T&;
};
template <class T>
struct MakeConst<T*> {
using type = const T*;
};

template <class Iterator>
class Enumerator {
public:
constexpr explicit Enumerator(Iterator it) : it_(std::move(it)) {}

class Proxy {
public:
using difference_type = ssize_t;
using value_type = typename std::iterator_traits<Iterator>::value_type;
using reference = typename std::iterator_traits<Iterator>::reference;
using pointer = typename std::iterator_traits<Iterator>::pointer;
using iterator_category = std::input_iterator_tag;

ARCTICDB_FORCE_INLINE constexpr explicit Proxy(const Enumerator& enumerator)
: index(enumerator.idx_), element(*enumerator.it_) {}

ARCTICDB_FORCE_INLINE constexpr reference operator*() { return element; }
ARCTICDB_FORCE_INLINE constexpr pointer operator->() {
return std::addressof(element);
}

ARCTICDB_FORCE_INLINE constexpr typename MakeConst<reference>::type
operator*() const {
return element;
}
ARCTICDB_FORCE_INLINE constexpr typename MakeConst<pointer>::type operator->()
const {
return std::addressof(element);
}

public:
const size_t index;
reference element;
};

ARCTICDB_FORCE_INLINE constexpr Proxy operator*() const { return Proxy(*this); }

ARCTICDB_FORCE_INLINE constexpr Enumerator& operator++() {
++it_;
++idx_;
return *this;
}

template <typename OtherIterator>
ARCTICDB_FORCE_INLINE constexpr bool operator==(
const Enumerator<OtherIterator>& rhs) const {
return it_ == rhs.it_;
}

template <typename OtherIterator>
ARCTICDB_FORCE_INLINE constexpr bool operator!=(
const Enumerator<OtherIterator>& rhs) const {
return !(it_ == rhs.it_);
}

private:
template <typename OtherIterator>
friend class Enumerator;

Iterator it_;
size_t idx_ = 0;
};

template <class RangeType>
class RangeEnumerator {
RangeType r_;
using BeginIteratorType = decltype(std::declval<RangeType>().begin());
using EndIteratorType = decltype(std::declval<RangeType>().end());

public:
constexpr explicit RangeEnumerator(RangeType&& r) : r_(std::forward<RangeType>(r)) {}

constexpr Enumerator<BeginIteratorType> begin() {
return Enumerator<BeginIteratorType>(r_.begin());
}
constexpr Enumerator<EndIteratorType> end() {
return Enumerator<EndIteratorType>(r_.end());
}
};

} // namespace detail

template <class RangeType>
constexpr detail::RangeEnumerator<RangeType> enumerate(RangeType&& r) {
return detail::RangeEnumerator<RangeType>(std::forward<RangeType>(r));
}

} // namespace arcticdb
6 changes: 6 additions & 0 deletions cpp/arcticdb/util/preprocess.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@
#define ARCTICDB_LIKELY
#define ARCTICDB_UNLIKELY
#endif

#ifdef _MSC_VER
#define ARCTICDB_FORCE_INLINE __forceinline
#elif defined(__GNUC__)
#define ARCTICDB_FORCE_INLINE inline __attribute__((__always_inline__))
#else
14 changes: 14 additions & 0 deletions cpp/arcticdb/util/test/test_enumerate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include <arcticdb/util/enumerate.hpp>
#include <arcticdb/log/log.hpp>

TEST(Enumerate, Vector) {
std::vector<int> vec = {1, 2, 3, 4};

using namespace arcticdb;

for(auto&& [thing, index] : enumerate(vec)) {
arcticdb::log::version().info("{} : {}", thing, index);
}
}

0 comments on commit 90770ed

Please sign in to comment.