1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef KEYWORDS_DWA2002323_HPP
6 # define KEYWORDS_DWA2002323_HPP
7 
8 # include <boost/python/detail/prefix.hpp>
9 
10 # include <boost/python/args_fwd.hpp>
11 # include <boost/config.hpp>
12 # include <boost/python/detail/preprocessor.hpp>
13 # include <boost/python/detail/type_list.hpp>
14 
15 # include <boost/type_traits/is_reference.hpp>
16 # include <boost/type_traits/remove_reference.hpp>
17 # include <boost/type_traits/remove_cv.hpp>
18 
19 # include <boost/preprocessor/enum_params.hpp>
20 # include <boost/preprocessor/repeat.hpp>
21 # include <boost/preprocessor/facilities/intercept.hpp>
22 # include <boost/preprocessor/iteration/local.hpp>
23 
24 # include <boost/python/detail/mpl_lambda.hpp>
25 # include <boost/python/object_core.hpp>
26 
27 # include <boost/mpl/bool.hpp>
28 
29 # include <cstddef>
30 # include <algorithm>
31 
32 namespace boost { namespace python {
33 
34 typedef detail::keywords<1> arg;
35 typedef arg arg_; // gcc 2.96 workaround
36 
37 namespace detail
38 {
39   template <std::size_t nkeywords>
40   struct keywords_base
41   {
42       BOOST_STATIC_CONSTANT(std::size_t, size = nkeywords);
43 
rangeboost::python::detail::keywords_base44       keyword_range range() const
45       {
46           return keyword_range(elements, elements + nkeywords);
47       }
48 
49       keyword elements[nkeywords];
50 
51       keywords<nkeywords+1>
52       operator,(python::arg const &k) const;
53 
54       keywords<nkeywords + 1>
55       operator,(char const *name) const;
56   };
57 
58   template <std::size_t nkeywords>
59   struct keywords : keywords_base<nkeywords>
60   {
61   };
62 
63   template <>
64   struct keywords<1> : keywords_base<1>
65   {
keywordsboost::python::detail::keywords66       explicit keywords(char const *name)
67       {
68           elements[0].name = name;
69       }
70 
71       template <class T>
operator =boost::python::detail::keywords72       python::arg& operator=(T const& value)
73       {
74           object z(value);
75           elements[0].default_value = handle<>(python::borrowed(object(value).ptr()));
76           return *this;
77       }
78 
operator detail::keyword const&boost::python::detail::keywords79       operator detail::keyword const&() const
80       {
81           return elements[0];
82       }
83   };
84 
85   template <std::size_t nkeywords>
86   inline
87   keywords<nkeywords+1>
operator ,(python::arg const & k) const88   keywords_base<nkeywords>::operator,(python::arg const &k) const
89   {
90       keywords<nkeywords> const& l = *static_cast<keywords<nkeywords> const*>(this);
91       python::detail::keywords<nkeywords+1> res;
92       std::copy(l.elements, l.elements+nkeywords, res.elements);
93       res.elements[nkeywords] = k.elements[0];
94       return res;
95   }
96 
97   template <std::size_t nkeywords>
98   inline
99   keywords<nkeywords + 1>
operator ,(char const * name) const100   keywords_base<nkeywords>::operator,(char const *name) const
101   {
102       return this->operator,(python::arg(name));
103   }
104 
105 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
106   template<typename T>
107   struct is_keywords
108   {
109       BOOST_STATIC_CONSTANT(bool, value = false);
110   };
111 
112   template<std::size_t nkeywords>
113   struct is_keywords<keywords<nkeywords> >
114   {
115       BOOST_STATIC_CONSTANT(bool, value = true);
116   };
117   template <class T>
118   struct is_reference_to_keywords
119   {
120       BOOST_STATIC_CONSTANT(bool, is_ref = is_reference<T>::value);
121       typedef typename remove_reference<T>::type deref;
122       typedef typename remove_cv<deref>::type key_t;
123       BOOST_STATIC_CONSTANT(bool, is_key = is_keywords<key_t>::value);
124       BOOST_STATIC_CONSTANT(bool, value = (is_ref & is_key));
125 
126       typedef mpl::bool_<value> type;
127       BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T))
128   };
129 # else
130   typedef char (&yes_keywords_t)[1];
131   typedef char (&no_keywords_t)[2];
132 
133   no_keywords_t is_keywords_test(...);
134 
135   template<std::size_t nkeywords>
136   yes_keywords_t is_keywords_test(void (*)(keywords<nkeywords>&));
137 
138   template<std::size_t nkeywords>
139   yes_keywords_t is_keywords_test(void (*)(keywords<nkeywords> const&));
140 
141   template<typename T>
142   class is_reference_to_keywords
143   {
144    public:
145       BOOST_STATIC_CONSTANT(
146           bool, value = (
147               sizeof(detail::is_keywords_test( (void (*)(T))0 ))
148               == sizeof(detail::yes_keywords_t)));
149 
150       typedef mpl::bool_<value> type;
151       BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T))
152   };
153 # endif
154 }
155 
args(char const * name)156 inline detail::keywords<1> args(char const* name)
157 {
158     return detail::keywords<1>(name);
159 }
160 
161 #  define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n;
162 #  define BOOST_PP_LOCAL_MACRO(n)                                               \
163 inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name)) \
164 {                                                                               \
165     detail::keywords<n> result;                                                 \
166     BOOST_PP_REPEAT_1(n, BOOST_PYTHON_ASSIGN_NAME, _)                           \
167     return result;                                                              \
168 }
169 #  define BOOST_PP_LOCAL_LIMITS (2, BOOST_PYTHON_MAX_ARITY)
170 #  include BOOST_PP_LOCAL_ITERATE()
171 
172 }} // namespace boost::python
173 
174 
175 # endif // KEYWORDS_DWA2002323_HPP
176