Skip to content

Instantly share code, notes, and snippets.

@amedama41
Created February 23, 2014 01:10
Show Gist options
  • Save amedama41/9165134 to your computer and use it in GitHub Desktop.
Save amedama41/9165134 to your computer and use it in GitHub Desktop.
BGL property iterator for Boost.Fusion
#ifndef CANARD_PROPERTY_SEQUENCE_BEGIN_IMPL_HPP
#define CANARD_PROPERTY_SEQUENCE_BEGIN_IMPL_HPP
#include <boost/fusion/sequence/intrinsic.hpp>
#include "property_sequence.hpp"
#include "property_iterator.hpp"
namespace boost {
namespace fusion {
namespace extension {
template <>
struct begin_impl<canard::property_tag>
{
template <class Property>
struct apply
{
using type = canard::property_iterator<Property>;
static type call(Property& p)
{
return type{p};
}
};
};
}
}
}
#endif
#ifndef CANARD_PROPERTY_SEQUENCE_END_IMPL_HPP
#define CANARD_PROPERTY_SEQUENCE_END_IMPL_HPP
#include <boost/fusion/sequence/intrinsic.hpp>
#include "property_sequence.hpp"
#include "property_iterator.hpp"
namespace boost {
namespace fusion {
namespace extension {
template <>
struct end_impl<canard::property_tag>
{
template <class Property>
struct apply
{
using type = canard::property_iterator<boost::no_property>;
static type call(Property& p)
{
return type{};
}
};
};
}
}
}
#endif
#ifndef CANARD_PROPERTY_SEQUENCE_ITERATOR_HPP
#define CANARD_PROPERTY_SEQUENCE_ITERATOR_HPP
#include <cstddef>
#include <boost/graph/properties.hpp>
#include <boost/fusion/iterator/iterator_facade.hpp>
namespace canard {
template <class T>
struct property_iterator;
template <class Tag, class T, class Base>
struct property_iterator<boost::property<Tag, T, Base>>
: boost::fusion::iterator_facade<
property_iterator<boost::property<Tag, T, Base>>
, boost::fusion::associative_tag
>
{
using Property = boost::property<Tag, T, Base>;
property_iterator(Property& property)
: property_{property}
{
}
template <class Iterator>
struct value_of
{
using type = typename Iterator::Property;
};
template <class Iterator>
struct deref
{
using type = decltype((std::declval<Iterator>().property_));
static type call(Iterator const& it)
{
return it.property_;
}
};
template <class Iterator>
struct next
{
template <class U>
struct next_type
{
using type = boost::no_property;
};
template <class Tag2, class T2, class Base2>
struct next_type<boost::property<Tag2, T2, Base2>>
{
using type = boost::property<Tag2, T2, Base2>;
};
using type = property_iterator<typename next_type<Base>::type>;
static type call(Iterator const& it)
{
return type{it.property_.m_base};
}
};
template <class Iterator, std::size_t N>
struct advance
{
using type = typename advance<next<Iterator>, N - 1>::type;
static type call(Iterator const& it)
{
return advance<typename next<Iterator>::type, N - 1>::call(next<Iterator>::call(it));
}
};
template <class Iterator>
struct advance<Iterator, 0>
{
using type = Iterator;
static type call(Iterator const& it)
{
return it;
}
};
template <class Iterator>
struct key_of
{
using type = typename Iterator::Property::tag_type;
};
template <class Iterator>
struct value_of_data
{
using type = typename Iterator::Property::value_type;
};
template <class Iterator>
struct deref_data
{
using type = decltype((std::declval<typename Iterator::Property>().m_value));
static type call(Iterator const& it)
{
return it.property_.m_value;
}
};
Property& property_;
};
template <>
struct property_iterator<boost::no_property>
: boost::fusion::iterator_facade<
property_iterator<boost::no_property>
, boost::fusion::associative_tag
>
{
property_iterator()
{
}
template <class T>
explicit property_iterator(T const&)
{
}
};
};
#endif
#ifndef CANARD_PROPERTY_SEQUENCE_SUPPORT_HPP
#define CANARD_PROPERTY_SEQUENCE_SUPPORT_HPP
#include <boost/fusion/support.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/graph/properties.hpp>
namespace canard {
struct property_tag;
}
namespace boost {
namespace fusion {
namespace extension {
template <>
struct is_sequence_impl<canard::property_tag>
{
template <class Property>
struct apply : boost::mpl::true_
{
};
};
template <>
struct category_of_impl<canard::property_tag>
{
template <class Property>
struct apply
{
struct type
: fusion::forward_traversal_tag
, fusion::associative_tag
{
};
};
};
}
namespace traits {
template <class Tag, class T, class Base>
struct tag_of<boost::property<Tag, T, Base>>
{
using type = canard::property_tag;
};
template <class Tag, class T, class Base>
struct tag_of<boost::property<Tag, T, Base> const>
{
using type = canard::property_tag;
};
}
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment