summaryrefslogtreecommitdiff
path: root/libs/lambda/test/extending_rt_traits.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/lambda/test/extending_rt_traits.cpp')
-rw-r--r--libs/lambda/test/extending_rt_traits.cpp394
1 files changed, 394 insertions, 0 deletions
diff --git a/libs/lambda/test/extending_rt_traits.cpp b/libs/lambda/test/extending_rt_traits.cpp
new file mode 100644
index 000000000..56916ab51
--- /dev/null
+++ b/libs/lambda/test/extending_rt_traits.cpp
@@ -0,0 +1,394 @@
+// extending_return_type_traits.cpp -- The Boost Lambda Library --------
+//
+// Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com)
+//
+// 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)
+//
+// For more information, see www.boost.org
+
+// -----------------------------------------------------------------------
+
+
+#include <boost/test/minimal.hpp> // see "Header Implementation Option"
+
+#include "boost/lambda/bind.hpp"
+#include "boost/lambda/lambda.hpp"
+#include "boost/lambda/detail/suppress_unused.hpp"
+
+#include <iostream>
+
+#include <functional>
+
+#include <algorithm>
+
+using boost::lambda::detail::suppress_unused_variable_warnings;
+
+class A {};
+class B {};
+
+using namespace boost::lambda;
+
+
+B operator--(const A&, int) { return B(); }
+B operator--(A&) { return B(); }
+B operator++(const A&, int) { return B(); }
+B operator++(A&) { return B(); }
+B operator-(const A&) { return B(); }
+B operator+(const A&) { return B(); }
+
+B operator!(const A&) { return B(); }
+
+B operator&(const A&) { return B(); }
+B operator*(const A&) { return B(); }
+
+namespace boost {
+namespace lambda {
+
+ // unary + and -
+template<class Act>
+struct plain_return_type_1<unary_arithmetic_action<Act>, A > {
+ typedef B type;
+};
+
+ // post incr/decr
+template<class Act>
+struct plain_return_type_1<post_increment_decrement_action<Act>, A > {
+ typedef B type;
+};
+
+ // pre incr/decr
+template<class Act>
+struct plain_return_type_1<pre_increment_decrement_action<Act>, A > {
+ typedef B type;
+};
+ // !
+template<>
+struct plain_return_type_1<logical_action<not_action>, A> {
+ typedef B type;
+};
+ // &
+template<>
+struct plain_return_type_1<other_action<addressof_action>, A> {
+ typedef B type;
+};
+ // *
+template<>
+struct plain_return_type_1<other_action<contentsof_action>, A> {
+ typedef B type;
+};
+
+
+} // lambda
+} // boost
+
+void ok(B /*b*/) {}
+
+void test_unary_operators()
+{
+ A a; int i = 1;
+ ok((++_1)(a));
+ ok((--_1)(a));
+ ok((_1++)(a));
+ ok((_1--)(a));
+ ok((+_1)(a));
+ ok((-_1)(a));
+ ok((!_1)(a));
+ ok((&_1)(a));
+ ok((*_1)(a));
+
+ BOOST_CHECK((*_1)(make_const(&i)) == 1);
+}
+
+class X {};
+class Y {};
+class Z {};
+
+Z operator+(const X&, const Y&) { return Z(); }
+Z operator-(const X&, const Y&) { return Z(); }
+X operator*(const X&, const Y&) { return X(); }
+
+Z operator/(const X&, const Y&) { return Z(); }
+Z operator%(const X&, const Y&) { return Z(); }
+
+class XX {};
+class YY {};
+class ZZ {};
+class VV {};
+
+// it is possible to support differently cv-qualified versions
+YY operator*(XX&, YY&) { return YY(); }
+ZZ operator*(const XX&, const YY&) { return ZZ(); }
+XX operator*(volatile XX&, volatile YY&) { return XX(); }
+VV operator*(const volatile XX&, const volatile YY&) { return VV(); }
+
+// the traits can be more complex:
+template <class T>
+class my_vector {};
+
+template<class A, class B>
+my_vector<typename return_type_2<arithmetic_action<plus_action>, A&, B&>::type>
+operator+(const my_vector<A>& /*a*/, const my_vector<B>& /*b*/)
+{
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
+ return my_vector<res_type>();
+}
+
+
+
+// bitwise ops:
+X operator<<(const X&, const Y&) { return X(); }
+Z operator>>(const X&, const Y&) { return Z(); }
+Z operator&(const X&, const Y&) { return Z(); }
+Z operator|(const X&, const Y&) { return Z(); }
+Z operator^(const X&, const Y&) { return Z(); }
+
+// comparison ops:
+
+X operator<(const X&, const Y&) { return X(); }
+Z operator>(const X&, const Y&) { return Z(); }
+Z operator<=(const X&, const Y&) { return Z(); }
+Z operator>=(const X&, const Y&) { return Z(); }
+Z operator==(const X&, const Y&) { return Z(); }
+Z operator!=(const X&, const Y&) { return Z(); }
+
+// logical
+
+X operator&&(const X&, const Y&) { return X(); }
+Z operator||(const X&, const Y&) { return Z(); }
+
+// arithh assignment
+
+Z operator+=( X&, const Y&) { return Z(); }
+Z operator-=( X&, const Y&) { return Z(); }
+Y operator*=( X&, const Y&) { return Y(); }
+Z operator/=( X&, const Y&) { return Z(); }
+Z operator%=( X&, const Y&) { return Z(); }
+
+// bitwise assignment
+Z operator<<=( X&, const Y&) { return Z(); }
+Z operator>>=( X&, const Y&) { return Z(); }
+Y operator&=( X&, const Y&) { return Y(); }
+Z operator|=( X&, const Y&) { return Z(); }
+Z operator^=( X&, const Y&) { return Z(); }
+
+// assignment
+class Assign {
+public:
+ void operator=(const Assign& /*a*/) {}
+ X operator[](const int& /*i*/) { return X(); }
+};
+
+
+
+namespace boost {
+namespace lambda {
+
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<arithmetic_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<arithmetic_action<multiply_action>, X, Y> {
+ typedef X type;
+};
+
+ // if you want to make a distinction between differently cv-qualified
+ // types, you need to specialize on a different level:
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, XX, YY> {
+ typedef YY type;
+};
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, const XX, const YY> {
+ typedef ZZ type;
+};
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, volatile XX, volatile YY> {
+ typedef XX type;
+};
+template<>
+struct return_type_2<arithmetic_action<multiply_action>, volatile const XX, const volatile YY> {
+ typedef VV type;
+};
+
+ // the mapping can be more complex:
+template<class A, class B>
+struct plain_return_type_2<arithmetic_action<plus_action>, my_vector<A>, my_vector<B> > {
+ typedef typename
+ return_type_2<arithmetic_action<plus_action>, A&, B&>::type res_type;
+ typedef my_vector<res_type> type;
+};
+
+ // bitwise binary:
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<bitwise_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<bitwise_action<leftshift_action>, X, Y> {
+ typedef X type;
+};
+
+ // comparison binary:
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<relational_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<relational_action<less_action>, X, Y> {
+ typedef X type;
+};
+
+ // logical binary:
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<logical_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<logical_action<and_action>, X, Y> {
+ typedef X type;
+};
+
+ // arithmetic assignment :
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<arithmetic_assignment_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<arithmetic_assignment_action<multiply_action>, X, Y> {
+ typedef Y type;
+};
+
+ // arithmetic assignment :
+ // you can do action groups
+template<class Act>
+struct plain_return_type_2<bitwise_assignment_action<Act>, X, Y> {
+ typedef Z type;
+};
+
+ // or specialize the exact action
+template<>
+struct plain_return_type_2<bitwise_assignment_action<and_action>, X, Y> {
+ typedef Y type;
+};
+
+ // assignment
+template<>
+struct plain_return_type_2<other_action<assignment_action>, Assign, Assign> {
+ typedef void type;
+};
+ // subscript
+template<>
+struct plain_return_type_2<other_action<subscript_action>, Assign, int> {
+ typedef X type;
+};
+
+
+} // end lambda
+} // end boost
+
+
+
+void test_binary_operators() {
+
+ X x; Y y;
+ (_1 + _2)(x, y);
+ (_1 - _2)(x, y);
+ (_1 * _2)(x, y);
+ (_1 / _2)(x, y);
+ (_1 % _2)(x, y);
+
+
+ // make a distinction between differently cv-qualified operators
+ XX xx; YY yy;
+ const XX& cxx = xx;
+ const YY& cyy = yy;
+ volatile XX& vxx = xx;
+ volatile YY& vyy = yy;
+ const volatile XX& cvxx = xx;
+ const volatile YY& cvyy = yy;
+
+ ZZ dummy1 = (_1 * _2)(cxx, cyy);
+ YY dummy2 = (_1 * _2)(xx, yy);
+ XX dummy3 = (_1 * _2)(vxx, vyy);
+ VV dummy4 = (_1 * _2)(cvxx, cvyy);
+
+ suppress_unused_variable_warnings(dummy1);
+ suppress_unused_variable_warnings(dummy2);
+ suppress_unused_variable_warnings(dummy3);
+ suppress_unused_variable_warnings(dummy4);
+
+ my_vector<int> v1; my_vector<double> v2;
+ my_vector<double> d = (_1 + _2)(v1, v2);
+
+ suppress_unused_variable_warnings(d);
+
+ // bitwise
+
+ (_1 << _2)(x, y);
+ (_1 >> _2)(x, y);
+ (_1 | _2)(x, y);
+ (_1 & _2)(x, y);
+ (_1 ^ _2)(x, y);
+
+ // comparison
+
+ (_1 < _2)(x, y);
+ (_1 > _2)(x, y);
+ (_1 <= _2)(x, y);
+ (_1 >= _2)(x, y);
+ (_1 == _2)(x, y);
+ (_1 != _2)(x, y);
+
+ // logical
+
+ (_1 || _2)(x, y);
+ (_1 && _2)(x, y);
+
+ // arithmetic assignment
+ (_1 += _2)(x, y);
+ (_1 -= _2)(x, y);
+ (_1 *= _2)(x, y);
+ (_1 /= _2)(x, y);
+ (_1 %= _2)(x, y);
+
+ // bitwise assignment
+ (_1 <<= _2)(x, y);
+ (_1 >>= _2)(x, y);
+ (_1 |= _2)(x, y);
+ (_1 &= _2)(x, y);
+ (_1 ^= _2)(x, y);
+
+}
+
+
+int test_main(int, char *[]) {
+ test_unary_operators();
+ test_binary_operators();
+ return 0;
+}
+
+
+
+
+
+