/*************************************************************************** * * 20.function.objects.cpp - test exercising [lib.std.function_objects] * * $Id: 20.function.objects.cpp 426701 2006-07-28 23:19:41Z sebor $ * *************************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * Copyright 2000-2006 Rogue Wave Software. * **************************************************************************/ #include #include #if defined (__HP_aCC) && _RWSTD_HP_aCC_MAJOR < 6 // working around an HP aCC bug (see PR #25378) # include // working around an HP aCC bug (see PR #24417) _USING (namespace std); #endif // HP aCC < 6 /**************************************************************************/ #ifdef _MSC_VER // shut up the idiotic MSVC 6.0 warning C4099: // type name first seen using 'struct' now seen using 'class' # pragma warning (disable: 4099) // another bogus warning C4700: // local variable used without having been initialized # pragma warning (disable: 4700) # if _MSC_VER <= 1300 // work around a bug where the compiler thinks that what's a struct // is really a class with all private members (PR #23795) # define class struct # endif #endif #ifndef _RWSTD_EXPLICIT_INSTANTIATION // explicitly instantiate # if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD) \ && (!defined (_COMPILER_VERSION) || _COMPILER_VERSION > 730) \ && (!defined (__EDG_VERSION__) || __EDG_VERSION__ > 244) // work around an EDG front end bug (see, for example, PR #25292) // verify that names are declared [only] in namespace std # define TEST_CLASS_DEF(name, Tparam) \ template class std::name Tparam; \ void name (void *name) # define TEST_CLASS_DEF_2(name, Tparam1, Tparam2) \ template class std::name Tparam1, Tparam2; \ void name (void *name) # define TEST_CLASS_DEF_3(name, Tparam1, Tparam2, Tparam3) \ template class std::name Tparam1, Tparam2, Tparam3; \ void name (void *name) # else // if defined (_RWSTD_NO_NAMESPACE) || defined (_RWSTD_NO_HONOR_STD) // verify that names do not collide with function argument names # define TEST_CLASS_DEF(name, Tparam) \ template class std::name Tparam; \ void foo (void *name) # define TEST_CLASS_DEF_2(name, Tparam1, Tparam2) \ template class std::name Tparam1, Tparam2; \ void foo (void *name) # define TEST_CLASS_DEF_3(name, Tparam1, Tparam2, Tparam3) \ template class std::name Tparam1, Tparam2, Tparam3; \ void foo (void *name) # endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD # if defined __GNUG__ && __GNUG__ < 3 && __GNU_MINOR__ < 96 // working around a bug in g++ 2.95.2 (PR #23151) # define TEST_FUNCTION_DEF(decl) \ _RWSTD_NAMESPACE (std) { \ template decl; \ } /* namespace std */ \ typedef void unused_typedef # else # define TEST_FUNCTION_DEF(decl) template decl # endif #else // if defined (_RWSTD_EXPLICIT_INSTANTIATION) // classes will implicitly instantiated below # if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD) // verify that names are declared [only[ in namespace std # define TEST_CLASS_DEF(name, ignore) void name (void *name) # define TEST_CLASS_DEF_2(name, ign1, ign2) void name (void *name) # define TEST_CLASS_DEF_3(name, ign1, ign2, ign3) void name (void *name) # else // if defined (_RWSTD_NO_NAMESPACE) || defined (_RWSTD_NO_HONOR_STD) # define TEST_CLASS_DEF(name, ignore) void foo (void *name) # define TEST_CLASS_DEF_2(name, ign1, ign2) void foo (void *name) # define TEST_CLASS_DEF_3(name, ign1, ign2, ign3) void foo (void *name) # endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD # define TEST_FUNCTION_DEF(ignore) void unused_typedef #endif // _RWSTD_EXPLICIT_INSTANTIATION TEST_CLASS_DEF_2 (unary_function, ); TEST_CLASS_DEF_3 (binary_function, ); TEST_CLASS_DEF (plus, ); TEST_CLASS_DEF (minus, ); TEST_CLASS_DEF (multiplies, ); TEST_CLASS_DEF (divides, ); TEST_CLASS_DEF (modulus, ); TEST_CLASS_DEF (negate, ); TEST_CLASS_DEF (equal_to, ); TEST_CLASS_DEF (not_equal_to, ); TEST_CLASS_DEF (greater, ); TEST_CLASS_DEF (less, ); TEST_CLASS_DEF (greater_equal, ); TEST_CLASS_DEF (less_equal, ); TEST_CLASS_DEF (logical_and, ); TEST_CLASS_DEF (logical_or, ); TEST_CLASS_DEF (logical_not, ); TEST_CLASS_DEF (unary_negate, >); TEST_FUNCTION_DEF ( std::unary_negate > std::not1 (const std::negate&)); TEST_CLASS_DEF (binary_negate, >); TEST_FUNCTION_DEF ( std::binary_negate > std::not2 (const std::equal_to&)); TEST_CLASS_DEF (binder1st, >); TEST_FUNCTION_DEF ( std::binder1st > std::bind1st (const std::plus&, const int&)); TEST_CLASS_DEF (binder2nd , >); TEST_FUNCTION_DEF ( std::binder2nd > std::bind2nd (const std::plus&, const int&)); /**************************************************************************/ // exercise 20.3.1 [lib.base] static void test_base () { rw_info (0, 0, __LINE__, "[lib.base]"); // verify that member types really are of the correct types std::unary_function::argument_type *argument = (int*)0; std::unary_function::result_type *result = (void*)0; std::binary_function::first_argument_type *a1 = (int*)0; std::binary_function::second_argument_type *a2 = (char*)0; std::binary_function::result_type *res = (void*)0; _RWSTD_UNUSED (argument); _RWSTD_UNUSED (result); _RWSTD_UNUSED (a1); _RWSTD_UNUSED (a2); _RWSTD_UNUSED (res); } #define TEST_UNARY_OP(fun, op, x) do { \ rw_info (0, 0, __LINE__, "std::" #fun); \ N::fun f CTOR_ARG_LIST; \ /* verify that fun is copy constructible and assignable */ \ const N::fun f_cpy1 (f); \ /* const to verify copy ctor const correctness */ \ const N::fun f_cpy2 = f; \ /* verify that fun publicly derives from unary_function */ \ const std::unary_function *pf = &f; \ _RWSTD_UNUSED (pf); \ /* verify member types and signature of operator () */ \ typedef N::fun fun_t; /* in case fun contains commas */ \ N::fun::result_type (N::fun::*pfun) \ UNARY_OP_ARG_LIST (fun_t) const = &N::fun::operator(); \ _RWSTD_UNUSED (pfun); \ /* exercise operator() */ \ rw_assert (f.operator() (x) == (op x), 0, __LINE__, \ #fun "().operator()(%i) == %i, got %i", \ x, (op x), f.operator()(x)); \ /* exercise operator() of the two copies */ \ rw_assert (f_cpy1.operator() (x) == (op x), 0, __LINE__, \ #fun "::" #fun "(const " #fun "&)"); \ rw_assert (f_cpy2.operator() (x) == (op x), 0, __LINE__, \ #fun "::operator=" #fun "(const " #fun "&)"); \ } while (0) #define TEST_BINARY_OP(fun, op, x, y) do { \ rw_info (0, 0, __LINE__, "std::" #fun); \ N::fun f CTOR_ARG_LIST; \ /* verify that fun is copy constructible and assignable */ \ const N::fun f_cpy1 (f); \ /* const to verify copy ctor const correctness */ \ const N::fun f_cpy2 = f; \ /* verify that fun publicly derives from binary_function */ \ const std::binary_function *pf = &f; \ _RWSTD_UNUSED (pf); \ /* verify member types and signature of operator () */ \ typedef N::fun fun_t; /* in case fun contains commas */ \ N::fun::result_type (N::fun::*pfun) \ BINARY_OP_ARG_LIST (fun_t) const = &N::fun::operator(); \ _RWSTD_UNUSED (pfun); \ rw_assert (f.operator() (x, y) == (x op y), 0, __LINE__, \ #fun "().operator()(%i, %i) == %i, got %i", \ x, y, (x op y), f.operator()(x, y)); \ /* exercise operator() of the two copies */ \ rw_assert (f_cpy1.operator() (x, y) == (x op y), 0, __LINE__, \ #fun "::" #fun "(const " #fun "&)"); \ rw_assert (f_cpy2.operator() (x, y) == (x op y), 0, __LINE__, \ #fun "::operator=" #fun "(const " #fun "&)"); \ } while (0) // tested fununctions are in namespace std #define N std // most but not all operator() take arguments by const reference #define UNARY_OP_ARG_LIST(fun) (const fun::argument_type&) #define BINARY_OP_ARG_LIST(fun) \ (const fun::first_argument_type&, const fun::second_argument_type&) // use default ctor in tests below #define CTOR_ARG_LIST // exercise 20.3.2 [lib.arithmetic.operations] static void test_arithmetic_operations () { rw_info (0, 0, __LINE__, "[lib.arithmetic.operations]"); // 20.3.2, p2 TEST_BINARY_OP (plus, +, 1, 2); // 20.3.2, p3 TEST_BINARY_OP (minus, -, 3, 2); // 20.3.2, p4 TEST_BINARY_OP (multiplies, *, 2, 3); // 20.3.2, p5 TEST_BINARY_OP (divides, /, 6, 3); // 20.3.2, p6 TEST_BINARY_OP (modulus, %, 7, 3); // 20.3.2, p7 TEST_UNARY_OP (negate, -, 1); // exercise extensions // tested fununctions are in a private namespace #undef N #define N _RW TEST_UNARY_OP (identity, +, 3); TEST_UNARY_OP (unary_plus, +, 4); TEST_UNARY_OP (bitwise_complement, ~, 5); TEST_BINARY_OP (bitwise_and, &, 0x0f, 0x05); TEST_BINARY_OP (bitwise_or, |, 0x0f, 0xf0); TEST_BINARY_OP (exclusive_or, ^, 0x0f, 0xf1); TEST_BINARY_OP (shift_left, <<, 3, 3); TEST_BINARY_OP (shift_right, >>, 15, 3); // remaining tested fununctions are in namespace std #undef N #define N std } /**************************************************************************/ // exercise 20.3.3 [lib.comparisons] static void test_comparisons () { rw_info (0, 0, __LINE__, "[lib.comparisons]"); // 20.3.3, p2 TEST_BINARY_OP (equal_to, ==, 1, 1); TEST_BINARY_OP (equal_to, ==, 1.0, 2.0); // 20.3.3, p3 TEST_BINARY_OP (not_equal_to, !=, 1, 1); TEST_BINARY_OP (not_equal_to, !=, 1.0, 2.0); // 20.3.3, p4 TEST_BINARY_OP (greater, >, 1, 1); TEST_BINARY_OP (greater, >, 2.0, 1.0); // 20.3.3, p5 TEST_BINARY_OP (less, <, 1, 1); TEST_BINARY_OP (less, <, 1.0, 2.0); // 20.3.3, p6 TEST_BINARY_OP (greater_equal, >=, 1, 1); TEST_BINARY_OP (greater_equal, >=, 1.0, 2.0); // 20.3.3, p7 TEST_BINARY_OP (less_equal, <=, 1, 1); TEST_BINARY_OP (less_equal, <=, 2.0, 1.0); // 20.3.3, p8 // ??? } /**************************************************************************/ // exercise 20.3.4 [lib.logical.operations] static void test_logical_operations () { rw_info (0, 0, __LINE__, "[lib.logical.operations]"); // 20.3.4, p2 TEST_BINARY_OP (logical_and, &&, 0, 1); TEST_BINARY_OP (logical_and, &&, 1.0, 2.0); // 20.3.4, p3 TEST_BINARY_OP (logical_or, ||, '\0', '\0'); TEST_BINARY_OP (logical_or, ||, 0, 1); TEST_BINARY_OP (logical_or, ||, 1.0, 2.0); // 20.3.4, p4 TEST_UNARY_OP (logical_not, !, 0); TEST_UNARY_OP (logical_not, !, 2.0); } // helpers to verify that each class' ctor is explicit // not defined since they must not be referenced if test is successful void is_explicit (const std::unary_negate >&); void is_explicit (const std::binary_negate >&); void is_explicit (const std::pointer_to_unary_function&); void is_explicit (const std::pointer_to_binary_function&); struct has_implicit_ctor { // NOT explicit has_implicit_ctor (const std::logical_not&) { } has_implicit_ctor (const std::equal_to&) { } has_implicit_ctor (int (*)(int)) { } has_implicit_ctor (int (*)(int, int)) { } }; /**************************************************************************/ void is_explicit (const has_implicit_ctor&) { } // exercise 20.3.5 [lib.negators] static void test_negators () { rw_info (0, 0, __LINE__, "[lib.negators]"); #ifndef _RWSTD_NO_EXPLICIT // verify that std::unary_negate<>() and std::binary_negate<>() // ctors are declared explicit is_explicit (std::logical_not()); #endif // _RWSTD_NO_EXPLICIT // use std::negate<> as an argument in negator ctors #undef CTOR_ARG_LIST #define CTOR_ARG_LIST \ = std::unary_negate > (std::logical_not ()) // 20.3.5, p2 TEST_UNARY_OP (unary_negate >, !!, 0); TEST_UNARY_OP (unary_negate >, !!, 1); // exercise the convenience function template std::not1() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::not1 (std::logical_not ()) // 20.3.5, p3 TEST_UNARY_OP (unary_negate >, !!, '\0'); TEST_UNARY_OP (unary_negate >, !!, '1'); // use std::equal_to<> as an argument in negator ctors #undef CTOR_ARG_LIST #define CTOR_ARG_LIST \ = std::binary_negate > (std::equal_to ()) // 20.3.5, p4 TEST_BINARY_OP (binary_negate >, !=, 0.0, 1.0); TEST_BINARY_OP (binary_negate >, !=, 1.0, 2.0); // use std::not_equal_to<> as an argument in negator ctors #undef CTOR_ARG_LIST #define CTOR_ARG_LIST \ = std::binary_negate > (std::not_equal_to ()) TEST_BINARY_OP (binary_negate >, ==, 0, 1); TEST_BINARY_OP (binary_negate >, ==, 1, 2); // exercise the convenience function template std::not2() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::not2 (std::equal_to ()) // 20.3.5, p5 TEST_BINARY_OP (binary_negate >, !=, 2, 2); TEST_BINARY_OP (binary_negate >, !=, 3, 4); } /**************************************************************************/ // exercise 20.3.6 [lib.binders] static void test_binders () { rw_info (0, 0, __LINE__, "[lib.binders]"); // make sure the protected names `op' and `value' are accessible struct binder1st_derivative: std::binder1st > { binder1st_derivative () : std::binder1st >(std::minus (), 0) { // test protected access rw_assert (0 == op (value, value), 0, __LINE__, "binder1st<>::op"); rw_assert (0 == operator()(value), 0, __LINE__, "binder1st<>::operator()"); value = 7; rw_assert (-7 == op (0, value), 0, __LINE__, "binder1st<>::value"); rw_assert (7 == operator()(0), 0, __LINE__, "binder1st<>::operator()"); } } b1st; _RWSTD_UNUSED (b1st); // make sure the protected names `op' and `value' are accessible struct binder2nd_derivative: std::binder2nd > { binder2nd_derivative () : std::binder2nd >(std::minus (), 0) { // test protected access rw_assert (0 == op (value, value), 0, __LINE__, "binder2nd<>::op"); rw_assert (0 == operator()(value), 0, __LINE__, "binder2nd<>::operator()"); value = 7; rw_assert (-7 == op (0, value), 0, __LINE__, "binder2nd<>::value"); rw_assert (-7 == operator()(0), 0, __LINE__, "binder2nd<>::operator()"); } } b2nd; _RWSTD_UNUSED (b2nd); #undef CTOR_ARG_LIST // broken out of the macro definition to work around // a bug in g++ 2.95.2 parser std::minus obj_minus; // use std::negate<> as an argument in negator ctors #define CTOR_ARG_LIST (obj_minus, 1) // 20.3.6.1, p1 and p2 TEST_UNARY_OP (binder1st >, 1 -, 0); TEST_UNARY_OP (binder1st >, 1 -, 1); // 20.3.6.3, p1 and p2 TEST_UNARY_OP (binder2nd >, -1 +, 0); TEST_UNARY_OP (binder2nd >, 1 -, 1); // exercise the convenience function template std::bind1st<>() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::bind1st (std::divides(), 6) // 20.3.6.2, p1 TEST_UNARY_OP (binder1st >, 6 /, 3); TEST_UNARY_OP (binder1st >, 6 /, 2); // exercise the convenience function template std::bind2nd<>() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::bind2nd (std::plus(), -2) // 20.3.6.4, p1 TEST_UNARY_OP (binder2nd >, -2 +, 0); TEST_UNARY_OP (binder2nd >, -2 +, 1); } /**************************************************************************/ // helpers to exercise pointer to function adapters int square (int i) { return i * i; } int shift (int i, int n) { return i << n; } // exercise 20.3.7 [lib.function.pointer.adaptors] static void test_function_pointer_adaptors () { rw_info (0, 0, __LINE__, "[lib.function.pointer.adaptors]"); #ifndef _RWSTD_NO_EXPLICIT // verify that the pointer to function adapters' ctors are explicit is_explicit ((int (*)(int))0); is_explicit ((int (*)(int, int))0); #endif // _RWSTD_NO_EXPLICIT // initialize pointer_to_unary_function with the address of square #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&::square) // operator() takes a value (as opposed to const reference) #undef UNARY_OP_ARG_LIST #define UNARY_OP_ARG_LIST(fun) (fun::argument_type) #define pointer_to_unary_function_int pointer_to_unary_function // 20.3.7, p2 TEST_UNARY_OP (pointer_to_unary_function_int, 4 *, 4); // exercise the convenience function template ptr_fun() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::ptr_fun (&::square) // 20.3.7, p3 TEST_UNARY_OP (pointer_to_unary_function_int, 5 *, 5); // initialize pointer_to_binary_function with the address of shift #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&::shift) // operator() takes values (as opposed to const references) #undef BINARY_OP_ARG_LIST #define BINARY_OP_ARG_LIST(fun) \ (fun::first_argument_type, fun::second_argument_type) #define pointer_to_binary_function_int pointer_to_binary_function // 20.3.7, p4 TEST_BINARY_OP (pointer_to_binary_function_int, <<, 1, 4); // exercise the convenience function template ptr_fun() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::ptr_fun (&::shift) // 20.3.7, p5 TEST_BINARY_OP (pointer_to_binary_function_int, <<, 2, 5); } /**************************************************************************/ struct Integer { int i_; // for convenience operator int () const { return i_; } // non-const members int square () { return i_ * i_; } int div (short n) { return i_ / n; } // const versions of the above members int const_square () const { return i_ * i_; } int const_div (short n) const { return i_ / n; } }; // helper to verify that each class' ctor is explicit // not defined since they must not be referenced if test is successful void is_explicit (const std::mem_fun_t&); struct has_implicit_ctor_from_member { // NOT explicit has_implicit_ctor_from_member (int (Integer::*)()) { } has_implicit_ctor_from_member (int (Integer::*)(short)) { } has_implicit_ctor_from_member (int (Integer::*)() const) { } has_implicit_ctor_from_member (int (Integer::*)(short) const) { } }; void is_explicit (const has_implicit_ctor_from_member&) { } // exercise 20.3.8 [lib.member.pointer.adaptors] static void test_member_pointer_adaptors () { rw_info (0, 0, __LINE__, "[lib.member.pointer.adaptors]"); #ifndef _RWSTD_NO_EXPLICIT // verify that the pointer to member adapters' ctors are explicit is_explicit ((int (Integer::*)())0); is_explicit ((int (Integer::*)(short))0); is_explicit ((int (Integer::*)() const)0); is_explicit ((int (Integer::*)(short) const)0); #endif // _RWSTD_NO_EXPLICIT #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::square) #define mem_fun_t_Integer_int mem_fun_t Integer int_obj = { 5 }; // 20.3.8, p2 TEST_UNARY_OP (mem_fun_t_Integer_int, 5 * (int)*, &int_obj); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun (&Integer::square) int_obj.i_ = 7; // 20.3.8, p4 TEST_UNARY_OP (mem_fun_t_Integer_int, 7 * (int)*, &int_obj); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::div) #define mem_fun1_t_int_Integer_short mem_fun1_t // 20.3.8, p3 TEST_BINARY_OP (mem_fun1_t_int_Integer_short, ->operator int() /, (&int_obj), 2); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun (&Integer::div) // 20.3.8, p4 TEST_BINARY_OP (mem_fun1_t_int_Integer_short, ->operator int() / , (&int_obj), -1); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::square) // operator() takes a reference (as opposed to const reference or value) #undef UNARY_OP_ARG_LIST #define UNARY_OP_ARG_LIST(fun) (fun::argument_type&) #define mem_fun_ref_t_Integer_int mem_fun_ref_t int_obj.i_ = -9; // 20.3.8, p5 TEST_UNARY_OP (mem_fun_ref_t_Integer_int, -9 * (int), int_obj); // exercise the convenience function template mem_fun_ref() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun_ref (&Integer::square) // 20.3.8, p7 TEST_UNARY_OP (mem_fun_ref_t_Integer_int, -9 * (int), int_obj); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::div) // operator() takes a reference and a value #undef BINARY_OP_ARG_LIST #define BINARY_OP_ARG_LIST(fun) \ (fun::first_argument_type&, fun::second_argument_type) #define mem_fun1_ref_t_int_Integer_short mem_fun1_ref_t // 20.3.8, p6 TEST_BINARY_OP (mem_fun1_ref_t_int_Integer_short, .operator int() /, int_obj, 3); // exercise the convenience function template mem_fun_ref() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun_ref (&Integer::div) // 20.3.8, p7 TEST_BINARY_OP (mem_fun1_ref_t_int_Integer_short, .operator int() /, int_obj, 3); /***************************************************************************/ #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::const_square) // operator() takes a const reference (as opposed to reference or value) #undef UNARY_OP_ARG_LIST #define UNARY_OP_ARG_LIST(fun) (fun::argument_type) #define const_mem_fun_t_Integer_int const_mem_fun_t int_obj.i_ = 5; // verify const-correctness const Integer &int_cref = int_obj; // 20.3.8, p2 TEST_UNARY_OP (const_mem_fun_t_Integer_int, 5 * (int)*, &int_cref); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun (&Integer::const_square) int_obj.i_ = 7; // 20.3.8, p4 TEST_UNARY_OP (const_mem_fun_t_Integer_int, 7 * (int)*, &int_cref); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::const_div) // operator() takes a const value and a value #undef BINARY_OP_ARG_LIST #define BINARY_OP_ARG_LIST(fun) \ (fun::first_argument_type, fun::second_argument_type) #define const_mem_fun1_t_int_Integer_short \ const_mem_fun1_t // 20.3.8, p3 TEST_BINARY_OP (const_mem_fun1_t_int_Integer_short, ->operator int() /, (&int_cref), 2); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun (&Integer::const_div) // 20.3.8, p4 TEST_BINARY_OP (const_mem_fun1_t_int_Integer_short, ->operator int() / , (&int_cref), -1); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::const_square) // operator() takes a reference (as opposed to const reference or value) #undef UNARY_OP_ARG_LIST #define UNARY_OP_ARG_LIST(fun) (const fun::argument_type&) #define const_mem_fun_ref_t_Integer_int const_mem_fun_ref_t int_obj.i_ = -9; // 20.3.8, p5 TEST_UNARY_OP (const_mem_fun_ref_t_Integer_int, -9 * (int), int_cref); // exercise the convenience function template const_mem_fun_ref() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun_ref (&Integer::const_square) // 20.3.8, p7 TEST_UNARY_OP (const_mem_fun_ref_t_Integer_int, -9 * (int), int_cref); #undef CTOR_ARG_LIST #define CTOR_ARG_LIST (&Integer::const_div) // operator() takes a const reference and a value #undef BINARY_OP_ARG_LIST #define BINARY_OP_ARG_LIST(fun) \ (const fun::first_argument_type&, fun::second_argument_type) #define const_mem_fun1_ref_t_int_Integer_short \ const_mem_fun1_ref_t // 20.3.8, p6 TEST_BINARY_OP (const_mem_fun1_ref_t_int_Integer_short, .operator int() /, int_cref, 3); // exercise the convenience function template const_mem_fun_ref() #undef CTOR_ARG_LIST #define CTOR_ARG_LIST = std::mem_fun_ref (&Integer::const_div) // 20.3.8, p7 TEST_BINARY_OP (const_mem_fun1_ref_t_int_Integer_short, .operator int() /, int_cref, 3); } /**************************************************************************/ static int run_test (int, char**) { // exercise 20.3.1 [lib.base] test_base (); // exercise 20.3.2 [lib.arithmetic.operations] test_arithmetic_operations (); // exercise 20.3.3 [lib.comparisons] test_comparisons (); // exercise 20.3.4 [lib.logical.operations] test_logical_operations (); // exercise 20.3.5 [lib.negators] test_negators (); // exercise 20.3.6 [lib.binders] test_binders (); // exercise 20.3.7 [lib.function.pointer.adaptors] test_function_pointer_adaptors (); // exercise 20.3.8 [lib.member.pointer.adaptors] test_member_pointer_adaptors (); return 0; } /**************************************************************************/ int main (int argc, char *argv[]) { return rw_test (argc, argv, __FILE__, "lib.std.function_objects", 0 /* no comment */, run_test, "", (void*)0 /* sentinel */); }