// Copyright David Abrahams 2002.

// Distributed under the Boost Software License, Version 1.0. (See

// accompanying file LICENSE_1_0.txt or copy at

// http://www.boost.org/LICENSE_1_0.txt)

#ifndef OBJECT_OPERATORS_DWA2002617_HPP

# define OBJECT_OPERATORS_DWA2002617_HPP



# include <boost/python/detail/prefix.hpp>



# include <boost/python/object_core.hpp>

# include <boost/python/call.hpp>

# include <boost/iterator/detail/enable_if.hpp>

# include <boost/mpl/bool.hpp>



# include <boost/iterator/detail/config_def.hpp>



namespace boost { namespace python { namespace api {



template <class X>

char is_object_operators_helper(object_operators<X> const*);

    

typedef char (&no_type)[2];

no_type is_object_operators_helper(...);



template <class X> X* make_ptr();



template <class L, class R = L>

struct is_object_operators

{

    enum {

        value 

        = (sizeof(api::is_object_operators_helper(api::make_ptr<L>()))

           + sizeof(api::is_object_operators_helper(api::make_ptr<R>()))

           < 4

        )

    };

    typedef mpl::bool_<value> type;

};



# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)

template <class L, class R, class T>

struct enable_binary

  : boost::iterators::enable_if<is_object_operators<L,R>, T>

{};

#  define BOOST_PYTHON_BINARY_RETURN(T) typename enable_binary<L,R,T>::type

# else

#  define BOOST_PYTHON_BINARY_RETURN(T) T

# endif



template <class U>

object object_operators<U>::operator()() const

{

    object_cref2 f = *static_cast<U const*>(this);

    return call<object>(f.ptr());

}





template <class U>

inline

object_operators<U>::operator bool_type() const

{

    object_cref2 x = *static_cast<U const*>(this);

    return PyObject_IsTrue(x.ptr()) ? &object::ptr : 0;

}



template <class U>

inline bool

object_operators<U>::operator!() const

{

    object_cref2 x = *static_cast<U const*>(this);

    return !PyObject_IsTrue(x.ptr());

}



# define BOOST_PYTHON_COMPARE_OP(op, opid)                              \

template <class L, class R>                                             \

BOOST_PYTHON_BINARY_RETURN(object) operator op(L const& l, R const& r)    \

{                                                                       \

    return PyObject_RichCompare(                                    \

        object(l).ptr(), object(r).ptr(), opid);                        \

}

# undef BOOST_PYTHON_COMPARE_OP

    

# define BOOST_PYTHON_BINARY_OPERATOR(op)                               \

BOOST_PYTHON_DECL object operator op(object const& l, object const& r); \

template <class L, class R>                                             \

BOOST_PYTHON_BINARY_RETURN(object) operator op(L const& l, R const& r)  \

{                                                                       \

    return object(l) op object(r);                                      \

}

BOOST_PYTHON_BINARY_OPERATOR(>)

BOOST_PYTHON_BINARY_OPERATOR(>=)

BOOST_PYTHON_BINARY_OPERATOR(<)

BOOST_PYTHON_BINARY_OPERATOR(<=)

BOOST_PYTHON_BINARY_OPERATOR(==)

BOOST_PYTHON_BINARY_OPERATOR(!=)

BOOST_PYTHON_BINARY_OPERATOR(+)

BOOST_PYTHON_BINARY_OPERATOR(-)

BOOST_PYTHON_BINARY_OPERATOR(*)

BOOST_PYTHON_BINARY_OPERATOR(/)

BOOST_PYTHON_BINARY_OPERATOR(%)

BOOST_PYTHON_BINARY_OPERATOR(<<)

BOOST_PYTHON_BINARY_OPERATOR(>>)

BOOST_PYTHON_BINARY_OPERATOR(&)

BOOST_PYTHON_BINARY_OPERATOR(^)

BOOST_PYTHON_BINARY_OPERATOR(|)

# undef BOOST_PYTHON_BINARY_OPERATOR



        

# define BOOST_PYTHON_INPLACE_OPERATOR(op)                              \

BOOST_PYTHON_DECL object& operator op(object& l, object const& r);      \

template <class R>                                                      \

object& operator op(object& l, R const& r)                              \

{                                                                       \

    return l op object(r);                                              \

}

BOOST_PYTHON_INPLACE_OPERATOR(+=)

BOOST_PYTHON_INPLACE_OPERATOR(-=)

BOOST_PYTHON_INPLACE_OPERATOR(*=)

BOOST_PYTHON_INPLACE_OPERATOR(/=)

BOOST_PYTHON_INPLACE_OPERATOR(%=)

BOOST_PYTHON_INPLACE_OPERATOR(<<=)

BOOST_PYTHON_INPLACE_OPERATOR(>>=)

BOOST_PYTHON_INPLACE_OPERATOR(&=)

BOOST_PYTHON_INPLACE_OPERATOR(^=)

BOOST_PYTHON_INPLACE_OPERATOR(|=)

# undef BOOST_PYTHON_INPLACE_OPERATOR



}}} // namespace boost::python



#include <boost/iterator/detail/config_undef.hpp>



#endif // OBJECT_OPERATORS_DWA2002617_HPP

