Logo Search packages:      
Sourcecode: zeroc-ice version File versions  Download package

Map.h

// **********************************************************************
//
// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

#ifndef FREEZE_MAP_H
#define FREEZE_MAP_H

#include <Ice/Ice.h>
#include <iterator>
#include <Freeze/DB.h>
#include <Freeze/Exception.h>
#include <Freeze/Connection.h>

//
// Berkeley DB's DbEnv
//
class DbEnv;

namespace Freeze
{

class IteratorHelper;
class MapHelper;

class MapIndexI;
class MapHelperI;
class IteratorHelperI;
class SharedDb;

class FREEZE_API KeyCompareBase : public IceUtil::Shared
{
public:
    KeyCompareBase(bool);

    bool compareEnabled() const;

    virtual int compare(const Key&, const Key&) = 0;

private:
    const bool _enabled;
};
typedef IceUtil::Handle<KeyCompareBase> KeyCompareBasePtr;

class FREEZE_API MapIndexBase : public KeyCompareBase
{
public:
    
    virtual ~MapIndexBase();

    const std::string& name() const;

    IteratorHelper* untypedFind(const Key&, bool, bool) const;
    IteratorHelper* untypedLowerBound(const Key&, bool) const;
    IteratorHelper* untypedUpperBound(const Key&, bool) const;

    int untypedCount(const Key&) const;

    //
    // Implemented by the generated code
    //
    virtual void marshalKey(const Value&, Key&) const = 0;

protected:

    MapIndexBase(const std::string&, bool);

    Ice::CommunicatorPtr _communicator;

private:

    friend class MapHelperI;
    friend class IteratorHelperI;
    friend class SharedDb;

    std::string _name;
    MapIndexI* _impl;
    const MapHelperI* _map;
};
typedef IceUtil::Handle<MapIndexBase> MapIndexBasePtr;

class FREEZE_API MapHelper
{
public:
    
    static MapHelper*
    create(const Freeze::ConnectionPtr& connection, 
         const std::string& dbName,
         const std::string& key,
         const std::string& value,
         const KeyCompareBasePtr&,
         const std::vector<MapIndexBasePtr>&,
         bool createDb);

    virtual ~MapHelper() = 0;

    virtual IteratorHelper*
    find(const Key&, bool) const = 0;

    virtual IteratorHelper*
    lowerBound(const Key&, bool) const = 0;

    virtual IteratorHelper*
    upperBound(const Key&, bool) const = 0;

    virtual void
    put(const Key&, const Value&) = 0;

    virtual size_t
    erase(const Key&) = 0;

    virtual size_t
    count(const Key&) const = 0;
    
    virtual void
    clear() = 0;

    virtual void
    destroy() = 0;

    virtual size_t
    size() const = 0;

    virtual void
    closeAllIterators() = 0;

    virtual const MapIndexBasePtr&
    index(const std::string&) const = 0;
};


class FREEZE_API IteratorHelper
{  
public:

    static IteratorHelper* 
    create(const MapHelper& m, bool readOnly);

    virtual 
    ~IteratorHelper() = 0;

    virtual IteratorHelper*
    clone() const = 0;
    
    virtual const Key* 
    get() const = 0;

    virtual void
    get(const Key*&, const Value*&) const = 0;
    
    virtual  void 
    set(const Value&) = 0;

    virtual void
    erase() = 0;

    virtual bool
    next() const = 0;
}; 


//
// Forward declaration
//
template <typename key_type, typename mapped_type, 
        typename KeyCodec, typename ValueCodec, typename Compare>
class Map;
template <typename key_type, typename mapped_type, 
        typename KeyCodec, typename ValueCodec, typename Compare>
class ConstIterator;

//
// This is necessary for MSVC support.
//
struct IteratorBase
{
    typedef std::forward_iterator_tag iterator_category;
};

//
// Database iterator. This implements a forward iterator with the
// restriction that it's only possible to explicitely write back into
// the database.
//
// Two iterators are equal if they use the same database and their
// current records have the same key.
//
// TODO: It's possible to implement bidirectional iterators, if
// necessary.
//
template<typename key_type, typename mapped_type, 
       typename KeyCodec, typename ValueCodec, typename Compare>
class Iterator : public IteratorBase
{
public:

    typedef ptrdiff_t difference_type;

    typedef std::pair<const key_type, const mapped_type> value_type;

    typedef value_type* pointer;

    typedef value_type& reference;

    Iterator(MapHelper& mapHelper, const Ice::CommunicatorPtr& communicator) :
      _helper(IteratorHelper::create(mapHelper, false)),
      _communicator(communicator),
      _refValid(false)
    {
    }

    Iterator(IteratorHelper* helper, const Ice::CommunicatorPtr& communicator) :
      _helper(helper),
      _communicator(communicator),
      _refValid(false)
    {
    }

    Iterator() :
        _refValid(false)
    {
    }

    Iterator(const Iterator& rhs) :
      _communicator(rhs._communicator),
        _refValid(false)
    {
      if(rhs._helper.get() != 0)
      {
          _helper.reset(rhs._helper->clone());
      }
    }

    Iterator& operator=(const Iterator& rhs)
    {
      if(this != &rhs)
      {
          if(rhs._helper.get() != 0)
          {
            _helper.reset(rhs._helper->clone());
          }
          else
          {
            _helper.reset();
          }
          _communicator = rhs._communicator;
          _refValid = false;
      }

      return *this;
    }

    ~Iterator()
    {
    }

    bool operator==(const Iterator& rhs) const
    {
      if(_helper.get() == rhs._helper.get())
      {
          return true;
      }
      
      if(_helper.get() != 0 && rhs._helper.get() != 0)
      {
          const Key* lhsKey = _helper->get();
          const Key* rhsKey = rhs._helper->get();
          
          if(lhsKey != 0 && rhsKey != 0)
          {
            return *lhsKey == *rhsKey;
          }
      }
      return false;
    }

    bool operator!=(const Iterator& rhs) const
    {
      return !(*this == rhs);
    }

    Iterator& operator++()
    {
      incr();
      return *this;
    }

    Iterator operator++(int)
    {
      Iterator tmp = *this;
      incr();
      return tmp;
    }

    //
    // Note that this doesn't follow the regular iterator mapping:
    //
    // value_type& operator*(), value_type operator*() const
    //
    value_type& operator*() const
    {
        if(!_refValid)
        {
            key_type key;
            mapped_type value;

            getCurrentValue(key, value);

            //
            // !IMPORTANT!
            //
            // This method has to cache the returned value to implement
            // operator->().
            //
            const_cast<key_type&>(_ref.first) = key;
            const_cast<mapped_type&>(_ref.second) = value;
            _refValid = true;
        }

      return _ref;
    }

    value_type* operator->() { return &(operator*()); }

    //
    // This special method allows writing back into the database.
    //
    void set(const mapped_type& value)
    {
      assert(_helper.get());

      Value v;
      ValueCodec::write(value, v, _communicator);
      _helper->set(v);
        _refValid = false;
    }

private:

    void incr()
    {
      assert(_helper.get() != 0);
      if(!_helper->next())
      {
          //
          // The iterator has been moved past the end, and is now
          // invalid.
          //
          _helper.reset();
      }
        _refValid = false;
    }

    void getCurrentValue(key_type& key, mapped_type& value) const
    {
      assert(_helper.get() != 0);

      const Key* k = 0;
      const Value* v = 0;
      _helper->get(k, v);
      assert(k != 0);
      assert(v != 0);

      KeyCodec::read(key, *k, _communicator);
      ValueCodec::read(value, *v, _communicator);
    }

    friend class ConstIterator<key_type, mapped_type, 
                         KeyCodec, ValueCodec, Compare>;
    friend class Map<key_type, mapped_type, 
                 KeyCodec, ValueCodec, Compare>;

    std::auto_ptr<IteratorHelper> _helper;
    Ice::CommunicatorPtr _communicator;
    //
    // Cached last return value. This is so that operator->() can
    // actually return a pointer. The cached value is reused across
    // multiple calls to operator->() if _refValid is true, which
    // avoids problems in certain situations. For example, if
    // _ref.second is an STL container and you use an STL algorithm
    // such as transform, STLport (debug build) asserts that the
    // addresses of the containers are the same. This would fail if
    // the same value was not returned on subsequent calls to
    // operator->().
    //
    mutable value_type _ref;
    mutable bool _refValid;
};

//
// See Iterator comments for design notes
//
template <typename key_type, typename mapped_type, 
        typename KeyCodec, typename ValueCodec, typename Compare>
class ConstIterator : public IteratorBase
{
public:

    typedef ptrdiff_t difference_type;

    typedef std::pair<const key_type, const mapped_type> value_type;

    typedef value_type* pointer;

    typedef value_type& reference;

    ConstIterator(MapHelper& mapHelper, const Ice::CommunicatorPtr& communicator) :
      _helper(IteratorHelper::create(mapHelper, true)), 
      _communicator(_communicator),
      _refValid(false)
    {
    }

    ConstIterator(IteratorHelper* helper, const Ice::CommunicatorPtr& communicator) :
      _helper(helper),
      _communicator(communicator),
      _refValid(false)
    {
    }

    ConstIterator() :
        _refValid(false)
    {
    }

    ConstIterator(const ConstIterator& rhs) :
      _communicator(rhs._communicator),
        _refValid(false)
    {
      if(rhs._helper.get() != 0)
      {
          _helper.reset(rhs._helper->clone());
      }
    }

    //
    // A Iterator can be converted to a ConstIterator (but not
    // vice versa) - same for operator=.
    //
    ConstIterator(const Iterator<key_type, mapped_type, 
              KeyCodec, ValueCodec, Compare>& rhs) :
        _refValid(false)
    {
      if(rhs._helper.get() != 0)
      {
          _helper.reset(rhs._helper->clone());
      }
      _communicator = rhs._communicator;
    }

    ConstIterator& operator=(const ConstIterator& rhs)
    {
      if(this != &rhs)
      {
          if(rhs._helper.get() != 0)
          {
            _helper.reset(rhs._helper->clone());
          }
          else
          {
            _helper.reset();
          }
          _communicator = rhs._communicator;
          _refValid = false;
      }

      return *this;
    }

    //
    // Create const_iterator from iterator.
    //
    ConstIterator& operator=(const Iterator<key_type, mapped_type, 
                       KeyCodec, ValueCodec, Compare>& rhs)
    {
      if(rhs._helper.get() != 0)
      {
          _helper.reset(rhs._helper->clone());
      }
      else
      {
          _helper.reset();
      }
      _communicator = rhs._communicator;
        _refValid = false;

      return *this;
    }

    ~ConstIterator()
    {
    }

    bool operator==(const ConstIterator& rhs)
    {
      if(_helper.get() == rhs._helper.get())
      {
          return true;
      }
      
      if(_helper.get() != 0 && rhs._helper.get() != 0)
      {
          const Key* lhsKey = _helper->get();
          const Key* rhsKey = rhs._helper->get();
          
          if(lhsKey != 0 && rhsKey != 0)
          {
            return *lhsKey == *rhsKey;
          }
      }
      return false;
    }

    bool operator!=(const ConstIterator& rhs)
    {
      return !(*this == rhs);
    }

    ConstIterator& operator++()
    {
      incr();
      return *this;
    }

    ConstIterator operator++(int)
    {
      ConstIterator tmp = *this;
      incr();
      return tmp;
    }

    //
    // Note that this doesn't follow the regular iterator mapping:
    //
    // value_type operator*() const
    //
    value_type& operator*() const
    {
        if(!_refValid)
        {
            key_type key;
            mapped_type value;
            
            getCurrentValue(key, value);

            //
            // !IMPORTANT!
            //
            // This method has to cache the returned value to implement
            // operator->().
            //
            const_cast<key_type&>(_ref.first) = key;
            const_cast<mapped_type&>(_ref.second) = value;
            _refValid = true;
        }

      return _ref;
    }

    pointer operator->() const { return &(operator*()); }

private:

    void incr()
    {
      assert(_helper.get() != 0);
      if(!_helper->next())
      {
          //
          // The iterator has been moved past the end, and is now
          // invalid.
          //
          _helper.reset();
      }
        _refValid = false;
    }

    void getCurrentValue(key_type& key, mapped_type& value) const
    {
      assert(_helper.get() != 0);

      const Key* k = 0;
      const Value* v = 0;
      _helper->get(k, v);
      assert(k != 0);
      assert(v != 0);

      KeyCodec::read(key, *k, _communicator);
      ValueCodec::read(value, *v, _communicator);
    }

    friend class Map<key_type, mapped_type, 
                 KeyCodec, ValueCodec, Compare>;

    std::auto_ptr<IteratorHelper> _helper;
    Ice::CommunicatorPtr _communicator;

    //
    // Cached last return value. This is so that operator->() can
    // actually return a pointer. The cached value is reused across
    // multiple calls to operator->() if _refValid is true, which
    // avoids problems in certain situations. For example, if
    // _ref.second is an STL container and you use an STL algorithm
    // such as transform, STLport (debug build) asserts that the
    // addresses of the containers are the same. This would fail
    // if the same value was not returned on subsequent calls
    // to operator->().
    //
    mutable value_type _ref;
    mutable bool _refValid;
};

#if defined(_MSC_VER) && (_MSC_VER <= 1300)
//
// Without partial template specialization
//
struct IceEncodingCompare
{
    bool operator()(...)
    {
      return false;
    }
};

template<typename Compare>
inline bool 
enableKeyCompare(const Compare&)
{
    return true;
}

template<> 
inline bool 
enableKeyCompare<IceEncodingCompare>(const IceEncodingCompare&)
{
    return false;
}
# else
struct IceEncodingCompare {};
#endif

template<typename key_type, typename KeyCodec, typename Compare>
class KeyCompare : public KeyCompareBase
{
public:
    KeyCompare(const Compare& compare, 
             const Ice::CommunicatorPtr& communicator) :
#if defined(_MSC_VER) && (_MSC_VER <= 1300)
      KeyCompareBase(enableKeyCompare(compare)),
#else
      KeyCompareBase(true),
#endif
      _compare(compare),
      _communicator(communicator)
    {}

    virtual int compare(const Key& dbKey1, const Key& dbKey2)
    {
      key_type key1;
      KeyCodec::read(key1, dbKey1, _communicator);
      key_type key2;
      KeyCodec::read(key2, dbKey2, _communicator);

      if(_compare(key1, key2))
      {
          return -1;
      }
      else if(_compare(key2, key1))
      {
          return 1;
      }
      else
      {
          return 0;
      }
    }
private:
    Compare _compare;
    Ice::CommunicatorPtr _communicator;
};

#if !defined(_MSC_VER) || (_MSC_VER >= 1300)
//
// Partial template specialization: 
// do nothing for the IceEncodingCompare comparator
//
template<typename key_type, typename KeyCodec>
class KeyCompare<key_type, KeyCodec, IceEncodingCompare> : public KeyCompareBase
{
public:
    KeyCompare(const IceEncodingCompare&, const Ice::CommunicatorPtr&):
      KeyCompareBase(false)
    {}

    virtual int compare(const Key& dbKey1, const Key& dbKey2)
    {
      assert(0);
      return 0;
    }
};
#endif

//
// Need to separate MapIndex template class because _communicator is
// set later
//
template<typename key_type, typename KeyCodec, typename Compare>
class MapIndex : public MapIndexBase
{
public:
    virtual int compare(const Key& dbKey1, const Key& dbKey2)
    {
      key_type key1;
      KeyCodec::read(key1, dbKey1, _communicator);
      key_type key2;
      KeyCodec::read(key2, dbKey2, _communicator);

      if(_compare(key1, key2))
      {
          return -1;
      }
      else if(_compare(key2, key1))
      {
          return 1;
      }
      else
      {
          return 0;
      }
    }

protected:
    MapIndex(const std::string& name, const Compare& compare) :
#if defined(_MSC_VER) && (_MSC_VER <= 1300)
      MapIndexBase(name, enableKeyCompare(compare)),
#else
      MapIndexBase(name, true),
#endif
      _compare(compare)
    {}

private:
    Compare _compare;
};

#if !defined(_MSC_VER) || (_MSC_VER >= 1300)
//
// Partial template specialization: 
// do nothing for the IceEncodingCompare comparator
//
template<typename key_type, typename KeyCodec>
class MapIndex<key_type, KeyCodec, IceEncodingCompare> : public MapIndexBase
{
public:
    virtual int compare(const Key& dbKey1, const Key& dbKey2)
    {
      assert(0);
      return 0;
    }

protected:
    MapIndex(const std::string& name, const IceEncodingCompare&):
      MapIndexBase(name, false)
    {}
};
#endif

//
// A sorted map, similar to a std::map, with one notable difference:
// operator[] is not provided.
//
//
// TODO: implement bidirectional iterators.
//
template<typename key_type, typename mapped_type, 
       typename KeyCodec, typename ValueCodec,
       typename Compare = IceEncodingCompare>
class Map
{
public:

    typedef std::pair<const key_type, const mapped_type> value_type;

    typedef Iterator<key_type, mapped_type, 
                 KeyCodec, ValueCodec, Compare> iterator;
    typedef ConstIterator<key_type, mapped_type, 
                    KeyCodec, ValueCodec, Compare> const_iterator;

    //
    // No definition for reference, const_reference, pointer or
    // const_pointer.
    //
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;

    //
    // Allocators are not supported.
    //
    // allocator_type
    //

    //
    // Constructors
    //
    Map(const Freeze::ConnectionPtr& connection, 
      const std::string& dbName,
      bool createDb = true,
      const Compare& compare = Compare()) :
      _communicator(connection->getCommunicator())
    { 
      KeyCompareBasePtr keyCompare = 
          new KeyCompare<key_type, KeyCodec, Compare>(compare, _communicator);
      std::vector<MapIndexBasePtr> indices;

      _helper.reset(MapHelper::create(connection, dbName, 
                              KeyCodec::typeId(), ValueCodec::typeId(),
                              keyCompare, indices, createDb));
    }

    template<class _InputIterator>
    Map(const Freeze::ConnectionPtr& connection, 
      const std::string& dbName, 
      bool createDb,
      _InputIterator first, _InputIterator last,
      const Compare& compare = Compare()) :
      _communicator(connection->getCommunicator())
    {
      KeyCompareBasePtr keyCompare = 
          new KeyCompare<key_type, KeyCodec, Compare>(compare, _communicator);

      std::vector<MapIndexBasePtr> indices;

      _helper.reset(MapHelper::create(connection, dbName, 
                              KeyCodec::typeId(), ValueCodec::typeId(),
                              keyCompare, indices, createDb));
      while(first != last)
      {
          put(*first);
          ++first;
      }
    }

    ~Map()
    {
    }

    bool operator==(const Map& rhs) const
    {
      //
      // This does a memberwise equality for the entire contents of
      // the database. While slow this is always correct. Database
      // equality is not necessarily correct in the context of a
      // transaction.
      //
      if(count() != rhs.count())
      {
          return false;
      }

      for(const_iterator p = rhs.begin() ; p != rhs.end() ; ++p)
      {
          const_iterator q = rhs.find(p->first);
          if(q == rhs.end())
          {
            return false;
          }
          if(p->second != q->second)
          {
            return false;
          }
      }
      return true;
    }

    bool operator!=(const Map& rhs) const
    {
      return !(*this == rhs);
    }
    
    void swap(Map& rhs)
    {
      MapHelper* tmp = _helper.release();
      _helper.reset(rhs._helper.release());
      rhs._helper.reset(tmp);
      
      Ice::CommunicatorPtr tmpCom = _communicator;
      _communicator = rhs._communicator;
      rhs._communicator = tmpCom;
    }

    iterator begin()
    {
      try
      {
          return iterator(IteratorHelper::create(*_helper.get(), false), _communicator);
      }
      catch(const NotFoundException&)
      {
          return iterator();
      }
    }
    const_iterator begin() const
    {
      try
      {
          return const_iterator(IteratorHelper::create(*_helper.get(), true), _communicator);
      }
      catch(const NotFoundException&)
      {
          return const_iterator();
      }
    }

    iterator end()
    {
      return iterator();
    }

    const_iterator end() const
    {
      return const_iterator();
    }

    bool empty() const
    {
      return size() == 0;
    }

    size_type size() const
    {
      return _helper->size();
    }

    size_type max_size() const
    {
      return 0xffffffff; // TODO: is this the max?
    }

    //
    // This method isn't implemented.
    //
    // mapped_type& operator[](const key_type& key)
    //

    //
    // This method isn't in the STLport library - but it's referenced
    // in "STL Tutorial and Reference Guide, Second Edition". It's not
    // currently implemented.
    //
    // const mapped_type& operator[](const key_type& key) const;
    //

    //
    // No allocators.
    //
    //allocator_type get_allocator() const;
    //
 
    iterator insert(iterator /*position*/, const value_type& key)
    {
      //
      // position is ignored.
      //
      Key k;
      KeyCodec::write(key.first, k, _communicator);
      
      iterator r = iterator(_helper->find(k, false), _communicator);

      if(r == end())
      {
          Value v;
          ValueCodec::write(key.second, v, _communicator);
          
          _helper->put(k, v);
          r = iterator(_helper->find(k, false), _communicator);
      }

      return r;
    }

    std::pair<iterator, bool> insert(const value_type& key)
    {
      Key k;
      KeyCodec::write(key.first, k, _communicator);

      iterator r = iterator(_helper->find(k, false), _communicator);
      bool inserted = false;

      if(r == end())
      {
          Value v;
          ValueCodec::write(key.second, v, _communicator);
          
          _helper->put(k, v);
          inserted = true;
          r = iterator(_helper->find(k, false), _communicator);
      }

      return std::pair<iterator, bool>(r, inserted);
    }

    template <typename InputIterator>
    void insert(InputIterator first, InputIterator last)
    {
      while(first != last)
      {
          insert(*first);
          ++first;
      }
    }

    void put(const value_type& key)
    {
      //
      // insert or replace
      //
      Key k;
      Value v;
      KeyCodec::write(key.first, k, _communicator);
      ValueCodec::write(key.second, v, _communicator);

      _helper->put(k, v);
    }

    template <typename InputIterator>
    void put(InputIterator first, InputIterator last)
    {
      while(first != last)
      {
          put(*first);
          ++first;
      }
    }

    void erase(iterator position)
    {
      assert(position._helper.get() != 0);
      position._helper->erase();
    }

    size_type erase(const key_type& key)
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return _helper->erase(k);
    }

    void erase(iterator first, iterator last)
    {
      while(first != last)
      {
          first._helper->erase();
          ++first;
      }
    }

    void clear()
    {
      _helper->clear();
    }

    
    //
    // destroy is not a standard function
    //
    void destroy()
    {
      _helper->destroy();
    }
    
    iterator find(const key_type& key)
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return iterator(_helper->find(k, false), _communicator);
    }

    const_iterator find(const key_type& key) const
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return const_iterator(_helper->find(k, true), _communicator);
    }

    size_type count(const key_type& key) const
    {
      Key k;
      KeyCodec::write(key, k, _communicator);
      
      return _helper->count(k);

    }

    iterator lower_bound(const key_type& key)
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return iterator(_helper->lowerBound(k, false), _communicator);
    }
    
    const_iterator lower_bound(const key_type& key) const
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return iterator(_helper->lowerBound(k, true), _communicator);
    }

    iterator upper_bound(const key_type& key)
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return iterator(_helper->upperBound(k, false), _communicator);
    }
    
    const_iterator upper_bound(const key_type& key) const
    {
      Key k;
      KeyCodec::write(key, k, _communicator);

      return iterator(_helper->upperBound(k, true), _communicator);
    }
    
    std::pair<iterator, iterator> equal_range(const key_type& key)
    {
      return std::make_pair(lower_bound(key), upper_bound(key));
    }

    std::pair<const_iterator, const_iterator> 
    equal_range(const key_type& key) const
    {
      return std::make_pair(lower_bound(key), upper_bound(key));
    }

    const Ice::CommunicatorPtr&
    communicator() const
    {
      return _communicator();
    }

protected:

    Map(const Ice::CommunicatorPtr& communicator) :
      _communicator(communicator)
    {
    }

    std::auto_ptr<MapHelper> _helper;
    const Ice::CommunicatorPtr _communicator;
};


}

//
// This is for MSVC.
//
# ifdef _STLP_USE_OLD_HP_ITERATOR_QUERIES
namespace std
{

// TODO: update.
template <class key_type, class mapped_type, 
        class KeyCodec, class ValueCodec, class Compare>
inline pair<const key_type, const mapped_type>*
value_type(const Freeze::Iterator<key_type, mapped_type, 
         KeyCodec, ValueCodec, Compare>&)
{
    return (pair<const key_type, const mapped_type>*)0;
}

template <class key_type, class mapped_type, 
        class KeyCodec, class ValueCodec, class Compare>
inline pair<const key_type, const mapped_type>*
value_type(const Freeze::ConstIterator<key_type, mapped_type, 
         KeyCodec, ValueCodec, Compare>&)
{
    return (pair<const key_type, const mapped_type>*)0;
}

inline forward_iterator_tag iterator_category(const Freeze::IteratorBase&)
{
    return forward_iterator_tag();
}

inline ptrdiff_t* distance_type(const Freeze::IteratorBase&) { return (ptrdiff_t*) 0; }

}

#endif

#endif

Generated by  Doxygen 1.6.0   Back to index