[ create a new paste ] login | about

Link: http://codepad.org/AJFIVbdY    [ raw code | fork ]

C++, pasted on Nov 29:
#ifndef ARX_EXT_QT_MAP_FOREACH_H
#define ARX_EXT_QT_MAP_FOREACH_H

#include "config.h"
#include <utility> /* For std::pair. */
#include <boost/iterator/iterator_adaptor.hpp>
#include <QHash>
#include <QMultiHash>
#include <QMap>
#include <QMultiMap>

/*
 * Qt associative containers are not compatible with stl associative containers
 * as they provide iterators over a set of mapped values, not over a set of 
 * key-value pairs.
 *
 * This problem is solved by introducing proper boost::range bindings for 
 * these containers.
 */

namespace arx { namespace detail {
// -------------------------------------------------------------------------- //
// QIteratorWrapper
// -------------------------------------------------------------------------- //
  template<class Iterator, class Value, class Reference>
  class QIteratorWrapper: public 
    boost::iterator_adaptor<
      QIteratorWrapper<Iterator, Value, Reference>, 
      Iterator,
      Value,
      boost::bidirectional_traversal_tag,
      Reference
    >
  {
  public:
    QIteratorWrapper() {}

    explicit QIteratorWrapper(const Iterator &iterator): 
      QIteratorWrapper::iterator_adaptor_(iterator) {}

    template<class OtherIterator, class OtherKey, class OtherT>
    QIteratorWrapper(const QIteratorWrapper<OtherIterator, OtherKey, OtherT> &other): 
      QIteratorWrapper::iterator_adaptor_(other.base()) {}

  private:
    friend class boost::iterator_core_access;

    Reference dereference() const { 
      return Reference(base().key(), base().value());
    }
  };

}} // namespace arx::detail

namespace boost {
  
#define ARX_REGISTER_QT_ITERATOR_WRAPPER(CONTAINER)                             \
  template<class Key, class T>                                                  \
  struct range_mutable_iterator<CONTAINER<Key, T> > {                           \
    typedef arx::detail::QIteratorWrapper<typename CONTAINER<Key, T>::iterator, std::pair<const Key, T>, std::pair<const Key &, T &> > type; \
  };                                                                            \
                                                                                \
  template<class Key, class T>                                                  \
  struct range_const_iterator<CONTAINER<Key, T> > {                             \
    typedef arx::detail::QIteratorWrapper<typename CONTAINER<Key, T>::const_iterator, std::pair<const Key, T>, std::pair<const Key &, const T &> > type; \
  };                                                                            \
                                                                                \
  template<class Key, class T>                                                  \
  inline typename range_mutable_iterator<CONTAINER<Key, T> >::type              \
  range_begin(CONTAINER<Key, T> &x) {                                           \
    return range_mutable_iterator<CONTAINER<Key, T> >::type(x.begin());         \
  }                                                                             \
                                                                                \
  template<class Key, class T>                                                  \
  inline typename range_const_iterator<CONTAINER<Key, T> >::type                \
  range_begin(const CONTAINER<Key, T> &x) {                                     \
    return range_const_iterator<CONTAINER<Key, T> >::type(x.begin());           \
  }                                                                             \
                                                                                \
  template<class Key, class T>                                                  \
  inline typename range_mutable_iterator<CONTAINER<Key, T> >::type              \
  range_end(CONTAINER<Key, T> &x) {                                             \
    return range_mutable_iterator<CONTAINER<Key, T> >::type(x.end());           \
  }                                                                             \
                                                                                \
  template<class Key, class T>                                                  \
  inline typename range_const_iterator<CONTAINER<Key, T> >::type                \
  range_end(const CONTAINER<Key, T> &x) {                                       \
    return range_const_iterator<CONTAINER<Key, T> >::type(x.end());             \
  }

  ARX_REGISTER_QT_ITERATOR_WRAPPER(QHash);
  ARX_REGISTER_QT_ITERATOR_WRAPPER(QMultiHash);
  ARX_REGISTER_QT_ITERATOR_WRAPPER(QMap);
  ARX_REGISTER_QT_ITERATOR_WRAPPER(QMultiMap);

#undef ARX_REGISTER_QT_ITERATOR_WRAPPER

} // namespace boost

#endif // ARX_EXT_QT_MAP_FOREACH_H


Create a new paste based on this one


Comments: