I'm currently working with the LLVM JIT framework. There is some graph I had to implement for internal cost bench-marking. It has cyclic node dependencies, so I have to use std::weak_ptr
pointers for nodes' children instead of their std::shared_ptr
counterparts. When it came to implementing child iterators for the graph's external interface, I've adapted llvm::iterator_base
.
template
<
typename WrappedIteratorT,
typename T = typename std::remove_reference < decltype(*(std::declval<WrappedIteratorT>()->lock())) >::type
>
struct weak_pointee_iterator
: public llvm::iterator_adaptor_base
<
weak_pointee_iterator<WrappedIteratorT>, WrappedIteratorT,
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
T
>
{
using strong_counterpart = decltype(std::declval<WrappedIteratorT>()->lock());
weak_pointee_iterator() = default;
template <typename U>
weak_pointee_iterator(U &&u)
: weak_pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u))
{}
bool tryLock() const
{
strongPointer_ = (*this->I).lock();
return strongPointer_ != nullptr;
}
T& operator*() const
{
if (tryLock()) {
return *strongPointer_;
} else {
llvm_unreachable("Weak pointer expired");
}
}
private:
mutable strong_counterpart strongPointer_;
};