// 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 #include "boost/lambda/lambda.hpp" #include "boost/lambda/detail/suppress_unused.hpp" #include #include #include #include #include #include #ifndef BOOST_NO_STRINGSTREAM #include #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::type ci(constant(i)); var_type::type vi(var(i)); (vi = _1)(make_const(100)); BOOST_TEST_EQ((ci)(), 5); BOOST_TEST_EQ(i, 100); int a; constant_ref_type::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 vi; vi.push_back(1); std::vector::iterator it = vi.begin(); (*_1 = 7)(it); BOOST_TEST_EQ(vi[0], 7); const std::vector::iterator cit(it); (*_1 = 8)(cit); BOOST_TEST_EQ(vi[0], 8); // TODO: Add tests for more complex iterator types boost::shared_ptr ptr(new int(0)); (*_1 = 7)(ptr); BOOST_TEST_EQ(*ptr, 7); const boost::shared_ptr 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(); }