2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-30 20:12:37 +00:00

Proxy object for an element in a container_proxy

[SVN r1562]
This commit is contained in:
Raoul Gough
2003-09-18 17:36:03 +00:00
parent 5f54f7f82b
commit bb376514b1

View File

@@ -0,0 +1,195 @@
// -*- mode:c++ -*-
//
// Header file element_proxy.hpp
//
// Proxy objects for invidivual elements in a container wrapped by
// container_proxy
//
// Copyright (c) 2003 Raoul M. Gough
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this material for any purpose is hereby
// granted without fee, provided the above notices are retained on all
// copies. Permission to modify the material and to distribute modified
// versions is granted, provided the above notices are retained, and a
// notice that the material was modified is included with the above
// copyright notice.
//
// History
// =======
// 2003/ 9/15 rmg File creation from container_proxy.hpp
//
// $Id$
//
#ifndef element_proxy_rmg_20030915_included
#define element_proxy_rmg_20030915_included
#include "shared_proxy_impl.hpp"
#include <boost/shared_ptr.hpp>
#include "value_traits.hpp"
#include <boost/get_pointer.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/register_ptr_to_python.hpp>
template<typename ContainerProxy>
class element_proxy
{
template<typename T> friend struct const_element_proxy;
typedef ContainerProxy container_proxy;
typedef typename container_proxy::shared_proxy proxy_type;
typedef boost::shared_ptr<proxy_type> proxy_pointer;
typedef typename container_proxy::raw_value_type raw_value_type;
typedef typename container_proxy::size_type size_type;
proxy_pointer mPtr;
public:
typedef typename proxy_type::value_type value_type;
typedef typename proxy_type::reference reference;
typedef typename proxy_type::pointer pointer;
typedef typename proxy_type::iterator_category iterator_category;
typedef typename proxy_type::difference_type difference_type;
typedef value_type element_type; // Alias for register_ptr_to_python
element_proxy () : mPtr () { }
explicit element_proxy (proxy_type *ptr) : mPtr (ptr) { }
element_proxy (proxy_pointer const &ptr) : mPtr (ptr) { }
explicit element_proxy (raw_value_type const &val)
: mPtr (new proxy_type(val))
{
// Create new standalone value (i.e. detached)
}
reference operator* () const { return mPtr->operator*(); }
pointer operator-> () const { return (*mPtr).operator->(); }
pointer get () const { return operator->(); } // Alias for pointer_holder
// Implicit conversion to raw_value_type
operator reference () const { return operator*(); }
// These are necessary (at least) while the indexing suite insists
// on converting the real container's value_type to the proxy
// container's value_type when going from Python to C++. If the
// suite would just pass the real container's value_type through,
// our implicit conversion to value_type might suffice.
bool operator== (value_type const &other) { return (**this) == other; }
bool operator!= (value_type const &other) { return (**this) != other; }
bool operator< (value_type const &other) { return (**this) < other; }
bool operator> (value_type const &other) { return (**this) > other; }
element_proxy &operator= (value_type const &copy)
{
proxy_type &proxy (*mPtr);
container_proxy *container = proxy.owner();
size_type index = proxy.index();
if (container)
{
container->replace (index, copy);
// Proxy was attached before, but is now detached. Make sure
// we now refer to the new element, instead of the detached
// copy of the old element
mPtr = container->at (index).mPtr;
// Note: in the special case that this we and the container
// proxy itself have the only references to the
// shared_proxy_impl, it is not necessary to first detach
// the proxy. Maybe best to implement when changing to
// intrusive_ptr instead of shared_ptr.
}
else
{
*proxy = copy;
}
return *this;
}
element_proxy &operator= (element_proxy const &copy)
{
// This is the most dubious bit of the fudge. The indexing_suite's
// implementation of __setitem__ tries to pass us our value_type,
// which is actually of type element_proxy
return (*this) = *copy;
}
size_t use_count() const { return mPtr.use_count(); } // For debugging
};
template<typename ContainerProxy>
struct const_element_proxy
{
typedef ContainerProxy container_proxy;
typedef typename container_proxy::shared_proxy proxy_type;
typedef boost::shared_ptr<proxy_type> proxy_pointer;
typedef typename container_proxy::raw_value_type raw_value_type;
proxy_pointer mPtr;
public:
typedef typename proxy_type::value_type const value_type;
typedef value_type &reference;
typedef value_type *pointer;
typedef typename proxy_type::iterator_category iterator_category;
typedef typename proxy_type::difference_type difference_type;
const_element_proxy () : mPtr () { }
explicit const_element_proxy (proxy_type *ptr) : mPtr (ptr) { }
const_element_proxy (proxy_pointer const &ptr) : mPtr (ptr) { }
const_element_proxy (element_proxy<container_proxy> const &copy)
: mPtr (copy.mPtr)
{
}
explicit const_element_proxy (raw_value_type const &val)
: mPtr (new proxy_type(val))
{
// Create new standalone value (i.e. detached)
}
reference operator* () const { return mPtr->operator*(); }
pointer operator-> () const { return mPtr->operator->(); }
// Implicit conversion to raw_value_type
operator reference () const { return operator*(); }
size_t use_count() const { return mPtr.use_count(); } // For debugging
};
namespace boost
{
template<typename ContainerProxy>
typename ContainerProxy::raw_value_type *
get_pointer (element_proxy<ContainerProxy> const &proxy)
{
return &(*proxy);
}
}
namespace indexing {
template<typename ContainerProxy>
struct value_traits<element_proxy<ContainerProxy> >
: public value_traits<typename ContainerProxy::raw_value_type>
{
template<typename PythonClass, typename Policy>
static void visitor_helper (PythonClass &, Policy const &)
{
typedef element_proxy<ContainerProxy> element_proxy_;
typedef typename ContainerProxy::raw_value_type raw_value_type;
boost::python::register_ptr_to_python<element_proxy_>();
boost::python::implicitly_convertible<raw_value_type, element_proxy_>();
}
};
}
#endif // element_proxy_rmg_20030915_included