123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- // 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;
- }
|