Initial C++0x support.
[luabind.git] / luabind / operator.hpp
blobf18f774ffd5d277e5545d4094746169a38a1e976
1 // Copyright (c) 2004 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef OPERATOR_040729_HPP
24 #define OPERATOR_040729_HPP
26 #include <boost/mpl/eval_if.hpp>
27 #include <boost/mpl/identity.hpp>
28 #include <boost/mpl/apply_wrap.hpp>
29 #ifndef LUABIND_CPP0x
30 #include <boost/preprocessor/repetition/enum_trailing.hpp>
31 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
32 #endif
33 #include <boost/type_traits/is_same.hpp>
34 #include <luabind/detail/other.hpp>
35 #include <luabind/raw_policy.hpp>
37 #if defined(__GNUC__) && __GNUC__ < 3
38 # define LUABIND_NO_STRINGSTREAM
39 #else
40 # if defined(BOOST_NO_STRINGSTREAM)
41 # define LUABIND_NO_STRINGSTREAM
42 # endif
43 #endif
45 #ifdef LUABIND_NO_STRINGSTREAM
46 #include <strstream>
47 #else
48 #include <sstream>
49 #endif
51 namespace luabind { namespace detail {
53 template<class W, class T> struct unwrap_parameter_type;
54 template<class Derived> struct operator_ {};
56 struct operator_void_return {};
58 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
59 template<class T>
60 inline T const& operator,(T const& x, operator_void_return)
62 return x;
64 #endif
66 }} // namespace luabind
68 namespace luabind { namespace operators {
70 # ifdef LUABIND_CPP0x
72 template <class Self, class... Args>
73 struct call_operator
74 : detail::operator_<call_operator>
76 call_operator(int)
79 template <class T, class Policies>
80 struct apply
82 static void execute(
83 lua_State* L
84 , typename detail::unwrap_parameter_type<T, Self>::type self
85 , detail::unwrap_parameter_type<T, Args>::type args...
88 using namespace detail;
89 operator_result(
91 , (self(args...), detail::operator_void_return())
92 , (Policies*)0
97 static char const* name() { return "__call"; }
100 # else // LUABIND_CPP_0x
101 #define BOOST_PP_ITERATION_PARAMS_1 (3, \
102 (0, LUABIND_MAX_ARITY, <luabind/detail/call_operator_iterate.hpp>))
103 #include BOOST_PP_ITERATE()
104 # endif // LUABIND_CPP_0x
106 }} // namespace luabind::operators
108 #ifndef LUABIND_CPP0x
109 # include <boost/preprocessor/iteration/local.hpp>
110 #endif
112 namespace luabind {
114 template<class Derived>
115 struct self_base
117 # ifdef LUABIND_CPP0x
119 template <class... Args>
120 operators::call_operator<Derived, Args...> operator()(Args const&...) const
122 return 0;
125 # else // LUABIND_CPP0x
127 operators::call_operator0<Derived> operator()() const
129 return 0;
132 #define BOOST_PP_LOCAL_MACRO(n) \
133 template<BOOST_PP_ENUM_PARAMS(n, class A)> \
134 BOOST_PP_CAT(operators::call_operator, n)< \
135 Derived \
136 BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \
138 operator()( \
139 BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \
140 ) const \
142 return 0; \
145 #define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY)
146 #include BOOST_PP_LOCAL_ITERATE()
148 # endif // LUABIND_CPP0x
152 struct self_type : self_base<self_type>
156 struct const_self_type : self_base<const_self_type>
160 namespace detail {
162 template<class W, class T>
163 struct unwrap_parameter_type
165 typedef typename boost::mpl::eval_if<
166 boost::is_same<T, self_type>
167 , boost::mpl::identity<W&>
168 , boost::mpl::eval_if<
169 boost::is_same<T, const_self_type>
170 , boost::mpl::identity<W const&>
171 , unwrap_other<T>
173 >::type type;
176 template<class Derived, class A, class B>
177 struct binary_operator
178 : operator_<binary_operator<Derived, A, B> >
180 binary_operator(int) {}
182 template<class T, class Policies>
183 struct apply
185 typedef typename unwrap_parameter_type<T, A>::type arg0;
186 typedef typename unwrap_parameter_type<T, B>::type arg1;
188 static void execute(lua_State* L, arg0 _0, arg1 _1)
190 Derived::template apply<arg0, arg1, Policies>::execute(
191 L, _0, _1);
195 static char const* name()
197 return Derived::name();
201 template<class Derived, class A>
202 struct unary_operator
203 : operator_<unary_operator<Derived, A> >
205 unary_operator(int) {}
207 template<class T, class Policies>
208 struct apply
210 typedef typename unwrap_parameter_type<T, A>::type arg0;
212 static void execute(lua_State* L, arg0 _0)
214 Derived::template apply<arg0, Policies>::execute(L, _0);
218 static char const* name()
220 return Derived::name();
224 template<class Policies>
225 inline void operator_result(lua_State* L, operator_void_return, Policies*)
229 namespace mpl = boost::mpl;
231 template<class T, class Policies>
232 inline void operator_result(lua_State* L, T const& x, Policies*)
234 typedef typename find_conversion_policy<
236 , Policies
237 >::type cv_policy;
239 typename mpl::apply_wrap2<cv_policy,T,cpp_to_lua>::type cv;
241 cv.apply(L, x);
244 }} // namespace detail::luabind
246 namespace luabind {
248 #define LUABIND_BINARY_OPERATOR(name_, op) \
249 namespace operators { \
251 struct name_ \
253 template<class T0, class T1, class Policies> \
254 struct apply \
256 static void execute(lua_State* L, T0 _0, T1 _1) \
258 detail::operator_result(L, _0 op _1, (Policies*)0); \
260 }; \
262 static char const* name() \
264 return "__" # name_; \
266 }; \
270 template<class T, class U> \
271 detail::binary_operator< \
272 operators::name_ \
273 , U \
274 , T \
276 inline operator op(self_base<U>, T const&) \
278 return 0; \
281 template<class T, class U> \
282 detail::binary_operator< \
283 operators::name_ \
284 , T \
285 , U \
287 inline operator op(T const&, self_base<U>) \
289 return 0; \
292 detail::binary_operator< \
293 operators::name_ \
294 , self_type \
295 , self_type \
297 inline operator op(self_type, self_type) \
299 return 0; \
302 detail::binary_operator< \
303 operators::name_ \
304 , self_type \
305 , const_self_type \
307 inline operator op(self_type, const_self_type) \
309 return 0; \
312 detail::binary_operator< \
313 operators::name_ \
314 , const_self_type \
315 , self_type \
317 inline operator op(const_self_type, self_type) \
319 return 0; \
322 detail::binary_operator< \
323 operators::name_ \
324 , const_self_type \
325 , const_self_type \
327 inline operator op(const_self_type, const_self_type) \
329 return 0; \
332 LUABIND_BINARY_OPERATOR(add, +)
333 LUABIND_BINARY_OPERATOR(sub, -)
334 LUABIND_BINARY_OPERATOR(mul, *)
335 LUABIND_BINARY_OPERATOR(div, /)
336 LUABIND_BINARY_OPERATOR(pow, ^)
337 LUABIND_BINARY_OPERATOR(lt, <)
338 LUABIND_BINARY_OPERATOR(le, <=)
339 LUABIND_BINARY_OPERATOR(eq, ==)
341 #undef LUABIND_UNARY_OPERATOR
343 #define LUABIND_UNARY_OPERATOR(name_, op, fn) \
344 namespace operators { \
346 struct name_ \
348 template<class T, class Policies> \
349 struct apply \
351 static void execute(lua_State* L, T x) \
353 detail::operator_result(L, op(x), (Policies*)0); \
355 }; \
357 static char const* name() \
359 return "__" # name_; \
361 }; \
365 template<class T> \
366 detail::unary_operator< \
367 operators::name_ \
368 , T \
370 inline fn(self_base<T>) \
372 return 0; \
375 template<class T>
376 std::string tostring_operator(T const& x)
378 #ifdef LUABIND_NO_STRINGSTREAM
379 std::strstream s;
380 s << x << std::ends;
381 #else
382 std::stringstream s;
383 s << x;
384 #endif
385 return s.str();
388 LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring)
389 LUABIND_UNARY_OPERATOR(unm, -, operator-)
391 #undef LUABIND_BINARY_OPERATOR
393 namespace {
395 LUABIND_ANONYMOUS_FIX self_type self;
396 LUABIND_ANONYMOUS_FIX const_self_type const_self;
398 } // namespace unnamed
400 } // namespace luabind
402 #endif // OPERATOR_040729_HPP