| // operator_tests_simple.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/core/lightweight_test.hpp> |
| |
| #include "boost/lambda/lambda.hpp" |
| |
| #include "boost/lambda/detail/suppress_unused.hpp" |
| |
| #include <boost/shared_ptr.hpp> |
| |
| #include <vector> |
| #include <map> |
| #include <set> |
| #include <string> |
| |
| #include <iostream> |
| |
| #ifndef BOOST_NO_STRINGSTREAM |
| #include <sstream> |
| #endif |
| |
| using namespace std; |
| using namespace boost; |
| |
| using namespace boost::lambda; |
| |
| |
| class unary_plus_tester {}; |
| unary_plus_tester operator+(const unary_plus_tester& a) { return a; } |
| |
| void cout_tests() |
| { |
| #ifndef BOOST_NO_STRINGSTREAM |
| using std::cout; |
| ostringstream os; |
| int i = 10; |
| (os << _1)(i); |
| |
| (os << constant("FOO"))(); |
| |
| BOOST_TEST_EQ(os.str(), std::string("10FOO")); |
| |
| |
| istringstream is("ABC 1"); |
| std::string s; |
| int k; |
| |
| is >> s; |
| is >> k; |
| |
| BOOST_TEST_EQ(s, std::string("ABC")); |
| BOOST_TEST_EQ(k, 1); |
| // test for constant, constant_ref and var |
| i = 5; |
| constant_type<int>::type ci(constant(i)); |
| var_type<int>::type vi(var(i)); |
| |
| (vi = _1)(make_const(100)); |
| BOOST_TEST_EQ((ci)(), 5); |
| BOOST_TEST_EQ(i, 100); |
| |
| int a; |
| constant_ref_type<int>::type cr(constant_ref(i)); |
| (++vi, var(a) = cr)(); |
| BOOST_TEST_EQ(i, 101); |
| #endif |
| } |
| |
| void arithmetic_operators() { |
| int i = 1; int j = 2; int k = 3; |
| |
| using namespace std; |
| using namespace boost::lambda; |
| |
| BOOST_TEST_EQ((_1 + 1)(i), 2); |
| BOOST_TEST_EQ(((_1 + 1) * _2)(i, j), 4); |
| BOOST_TEST_EQ((_1 - 1)(i), 0); |
| |
| BOOST_TEST_EQ((_1 * 2)(j), 4); |
| BOOST_TEST_EQ((_1 / 2)(j), 1); |
| |
| BOOST_TEST_EQ((_1 % 2)(k), 1); |
| |
| BOOST_TEST_EQ((-_1)(i), -1); |
| BOOST_TEST_EQ((+_1)(i), 1); |
| |
| // test that unary plus really does something |
| unary_plus_tester u; |
| unary_plus_tester up = (+_1)(u); |
| |
| boost::lambda::detail::suppress_unused_variable_warnings(up); |
| } |
| |
| void bitwise_operators() { |
| unsigned int ui = 2; |
| |
| BOOST_TEST_EQ((_1 << 1)(ui), (2 << 1)); |
| BOOST_TEST_EQ((_1 >> 1)(ui), (2 >> 1)); |
| |
| BOOST_TEST_EQ((_1 & 1)(ui), (2 & 1)); |
| BOOST_TEST_EQ((_1 | 1)(ui), (2 | 1)); |
| BOOST_TEST_EQ((_1 ^ 1)(ui), (2 ^ 1)); |
| BOOST_TEST_EQ((~_1)(ui), ~2u); |
| } |
| |
| void comparison_operators() { |
| int i = 0, j = 1; |
| |
| BOOST_TEST((_1 < _2)(i, j)); |
| BOOST_TEST((_1 <= _2)(i, j)); |
| BOOST_TEST(!(_1 == _2)(i, j)); |
| BOOST_TEST((_1 != _2)(i, j)); |
| BOOST_TEST(!(_1 > _2)(i, j)); |
| BOOST_TEST(!(_1 >= _2)(i, j)); |
| |
| BOOST_TEST(!(!(_1 < _2))(i, j)); |
| BOOST_TEST(!(!(_1 <= _2))(i, j)); |
| BOOST_TEST((!(_1 == _2))(i, j)); |
| BOOST_TEST(!(!(_1 != _2))(i, j)); |
| BOOST_TEST((!(_1 > _2))(i, j)); |
| BOOST_TEST((!(_1 >= _2))(i, j)); |
| } |
| |
| void logical_operators() { |
| |
| bool t = true, f = false; |
| BOOST_TEST((_1 && _2)(t, t)); |
| BOOST_TEST(!(_1 && _2)(t, f)); |
| BOOST_TEST(!(_1 && _2)(f, t)); |
| BOOST_TEST(!(_1 && _2)(f, f)); |
| |
| BOOST_TEST((_1 || _2)(t, t)); |
| BOOST_TEST((_1 || _2)(t, f)); |
| BOOST_TEST((_1 || _2)(f, t)); |
| BOOST_TEST(!(_1 || _2)(f, f)); |
| |
| BOOST_TEST(!(!_1)(t)); |
| BOOST_TEST((!_1)(f)); |
| |
| // test short circuiting |
| int i=0; |
| |
| (false && ++_1)(i); |
| BOOST_TEST_EQ(i, 0); |
| i = 0; |
| |
| (true && ++_1)(i); |
| BOOST_TEST_EQ(i, 1); |
| i = 0; |
| |
| (false || ++_1)(i); |
| BOOST_TEST_EQ(i, 1); |
| i = 0; |
| |
| (true || ++_1)(i); |
| BOOST_TEST_EQ(i, 0); |
| i = 0; |
| } |
| |
| void unary_incs_and_decs() { |
| int i = 0; |
| |
| BOOST_TEST_EQ(_1++(i), 0); |
| BOOST_TEST_EQ(i, 1); |
| i = 0; |
| |
| BOOST_TEST_EQ(_1--(i), 0); |
| BOOST_TEST_EQ(i, -1); |
| i = 0; |
| |
| BOOST_TEST_EQ((++_1)(i), 1); |
| BOOST_TEST_EQ(i, 1); |
| i = 0; |
| |
| BOOST_TEST_EQ((--_1)(i), -1); |
| BOOST_TEST_EQ(i, -1); |
| i = 0; |
| |
| // the result of prefix -- and ++ are lvalues |
| (++_1)(i) = 10; |
| BOOST_TEST_EQ(i, 10); |
| i = 0; |
| |
| (--_1)(i) = 10; |
| BOOST_TEST_EQ(i, 10); |
| i = 0; |
| } |
| |
| void compound_operators() { |
| |
| int i = 1; |
| |
| // normal variable as the left operand |
| (i += _1)(make_const(1)); |
| BOOST_TEST_EQ(i, 2); |
| |
| (i -= _1)(make_const(1)); |
| BOOST_TEST_EQ(i, 1); |
| |
| (i *= _1)(make_const(10)); |
| BOOST_TEST_EQ(i, 10); |
| |
| (i /= _1)(make_const(2)); |
| BOOST_TEST_EQ(i, 5); |
| |
| (i %= _1)(make_const(2)); |
| BOOST_TEST_EQ(i, 1); |
| |
| // lambda expression as a left operand |
| (_1 += 1)(i); |
| BOOST_TEST_EQ(i, 2); |
| |
| (_1 -= 1)(i); |
| BOOST_TEST_EQ(i, 1); |
| |
| (_1 *= 10)(i); |
| BOOST_TEST_EQ(i, 10); |
| |
| (_1 /= 2)(i); |
| BOOST_TEST_EQ(i, 5); |
| |
| (_1 %= 2)(i); |
| BOOST_TEST_EQ(i, 1); |
| |
| // lambda expression as a left operand with rvalue on RHS |
| (_1 += (0 + 1))(i); |
| BOOST_TEST_EQ(i, 2); |
| |
| (_1 -= (0 + 1))(i); |
| BOOST_TEST_EQ(i, 1); |
| |
| (_1 *= (0 + 10))(i); |
| BOOST_TEST_EQ(i, 10); |
| |
| (_1 /= (0 + 2))(i); |
| BOOST_TEST_EQ(i, 5); |
| |
| (_1 %= (0 + 2))(i); |
| BOOST_TEST_EQ(i, 1); |
| |
| // shifts |
| unsigned int ui = 2; |
| (_1 <<= 1)(ui); |
| BOOST_TEST_EQ(ui, (2 << 1)); |
| |
| ui = 2; |
| (_1 >>= 1)(ui); |
| BOOST_TEST_EQ(ui, (2 >> 1)); |
| |
| ui = 2; |
| (ui <<= _1)(make_const(1)); |
| BOOST_TEST_EQ(ui, (2 << 1)); |
| |
| ui = 2; |
| (ui >>= _1)(make_const(1)); |
| BOOST_TEST_EQ(ui, (2 >> 1)); |
| |
| // and, or, xor |
| ui = 2; |
| (_1 &= 1)(ui); |
| BOOST_TEST_EQ(ui, (2 & 1)); |
| |
| ui = 2; |
| (_1 |= 1)(ui); |
| BOOST_TEST_EQ(ui, (2 | 1)); |
| |
| ui = 2; |
| (_1 ^= 1)(ui); |
| BOOST_TEST_EQ(ui, (2 ^ 1)); |
| |
| ui = 2; |
| (ui &= _1)(make_const(1)); |
| BOOST_TEST_EQ(ui, (2 & 1)); |
| |
| ui = 2; |
| (ui |= _1)(make_const(1)); |
| BOOST_TEST_EQ(ui, (2 | 1)); |
| |
| ui = 2; |
| (ui ^= _1)(make_const(1)); |
| BOOST_TEST_EQ(ui, (2 ^ 1)); |
| |
| } |
| |
| void assignment_and_subscript() { |
| |
| // assignment and subscript need to be defined as member functions. |
| // Hence, if you wish to use a normal variable as the left hand argument, |
| // you must wrap it with var to turn it into a lambda expression |
| |
| using std::string; |
| string s; |
| |
| (_1 = "one")(s); |
| BOOST_TEST_EQ(s, string("one")); |
| |
| (var(s) = "two")(); |
| BOOST_TEST_EQ(s, string("two")); |
| |
| BOOST_TEST_EQ((var(s)[_1])(make_const(2)), 'o'); |
| BOOST_TEST_EQ((_1[2])(s), 'o'); |
| BOOST_TEST_EQ((_1[_2])(s, make_const(2)), 'o'); |
| |
| // subscript returns lvalue |
| (var(s)[_1])(make_const(1)) = 'o'; |
| BOOST_TEST_EQ(s, "too"); |
| |
| (_1[1])(s) = 'a'; |
| BOOST_TEST_EQ(s, "tao"); |
| |
| (_1[_2])(s, make_const(0)) = 'm'; |
| BOOST_TEST_EQ(s, "mao"); |
| |
| // TODO: tests for vector, set, map, multimap |
| } |
| |
| class A {}; |
| |
| void address_of_and_dereference() { |
| |
| A a; int i = 42; |
| |
| BOOST_TEST_EQ((&_1)(a), &a); |
| BOOST_TEST_EQ((*&_1)(i), 42); |
| |
| std::vector<int> vi; vi.push_back(1); |
| std::vector<int>::iterator it = vi.begin(); |
| |
| (*_1 = 7)(it); |
| BOOST_TEST_EQ(vi[0], 7); |
| const std::vector<int>::iterator cit(it); |
| (*_1 = 8)(cit); |
| BOOST_TEST_EQ(vi[0], 8); |
| |
| // TODO: Add tests for more complex iterator types |
| |
| boost::shared_ptr<int> ptr(new int(0)); |
| (*_1 = 7)(ptr); |
| BOOST_TEST_EQ(*ptr, 7); |
| const boost::shared_ptr<int> cptr(ptr); |
| (*_1 = 8)(cptr); |
| BOOST_TEST_EQ(*ptr, 8); |
| } |
| |
| |
| |
| void comma() { |
| |
| int i = 100; |
| BOOST_TEST_EQ((_1 = 10, 2 * _1)(i), 20); |
| |
| // TODO: that the return type is the exact type of the right argument |
| // (that r/l valueness is preserved) |
| |
| } |
| |
| void pointer_arithmetic() { |
| |
| int ia[4] = { 1, 2, 3, 4 }; |
| int* ip = ia; |
| int* ia_last = &ia[3]; |
| |
| const int cia[4] = { 1, 2, 3, 4 }; |
| const int* cip = cia; |
| const int* cia_last = &cia[3]; |
| |
| |
| // non-const array |
| BOOST_TEST_EQ((*(_1 + 1))(ia), 2); |
| |
| // non-const pointer |
| BOOST_TEST_EQ((*(_1 + 1))(ip), 2); |
| |
| BOOST_TEST_EQ((*(_1 - 1))(ia_last), 3); |
| |
| // const array |
| BOOST_TEST_EQ((*(_1 + 1))(cia), 2); |
| // const pointer |
| BOOST_TEST_EQ((*(_1 + 1))(cip), 2); |
| BOOST_TEST_EQ((*(_1 - 1))(cia_last), 3); |
| |
| // pointer arithmetic should not make non-consts const |
| (*(_1 + 2))(ia) = 0; |
| (*(_1 + 3))(ip) = 0; |
| |
| BOOST_TEST_EQ(ia[2], 0); |
| BOOST_TEST_EQ(ia[3], 0); |
| |
| // pointer - pointer |
| BOOST_TEST_EQ((_1 - _2)(ia_last, ia), 3); |
| BOOST_TEST_EQ((_1 - _2)(cia_last, cia), 3); |
| BOOST_TEST_EQ((ia_last - _1)(ia), 3); |
| BOOST_TEST_EQ((cia_last - _1)(cia), 3); |
| BOOST_TEST_EQ((cia_last - _1)(cip), 3); |
| |
| } |
| |
| int main() |
| { |
| arithmetic_operators(); |
| bitwise_operators(); |
| comparison_operators(); |
| logical_operators(); |
| unary_incs_and_decs(); |
| compound_operators(); |
| assignment_and_subscript(); |
| address_of_and_dereference(); |
| comma(); |
| pointer_arithmetic(); |
| cout_tests(); |
| return boost::report_errors(); |
| } |