summaryrefslogtreecommitdiff
path: root/boost/python/object_operators.hpp
blob: d436bb0144a8e8ca9ca3fbad8a1d5a1b5d45d876 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// 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);
    int is_true = PyObject_IsTrue(x.ptr());
    if (is_true < 0) throw_error_already_set();
    return is_true ? &object::ptr : 0;
}

template <class U>
inline bool
object_operators<U>::operator!() const
{
    object_cref2 x = *static_cast<U const*>(this);
    int is_true = PyObject_IsTrue(x.ptr());
    if (is_true < 0) throw_error_already_set();
    return !is_true;
}

# 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