| /*************************************************************************** |
| * |
| * 20.function.objects.cpp - test exercising [lib.std.function_objects] |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * 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 <functional> |
| #include <driver.h> |
| |
| #if defined (__HP_aCC) && _RWSTD_HP_aCC_MAJOR < 6 |
| |
| // working around an HP aCC bug (see PR #25378) |
| # include <string> |
| |
| // 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, <int, int>); |
| TEST_CLASS_DEF_3 (binary_function, <int, int, int>); |
| |
| TEST_CLASS_DEF (plus, <int>); |
| TEST_CLASS_DEF (minus, <int>); |
| TEST_CLASS_DEF (multiplies, <int>); |
| TEST_CLASS_DEF (divides, <int>); |
| TEST_CLASS_DEF (modulus, <int>); |
| TEST_CLASS_DEF (negate, <int>); |
| |
| TEST_CLASS_DEF (equal_to, <int>); |
| TEST_CLASS_DEF (not_equal_to, <int>); |
| TEST_CLASS_DEF (greater, <int>); |
| TEST_CLASS_DEF (less, <int>); |
| TEST_CLASS_DEF (greater_equal, <int>); |
| TEST_CLASS_DEF (less_equal, <int>); |
| |
| TEST_CLASS_DEF (logical_and, <int>); |
| TEST_CLASS_DEF (logical_or, <int>); |
| TEST_CLASS_DEF (logical_not, <int>); |
| |
| TEST_CLASS_DEF (unary_negate, <std::negate<int> >); |
| |
| TEST_FUNCTION_DEF ( |
| std::unary_negate<std::negate<int> > |
| std::not1 (const std::negate<int>&)); |
| |
| TEST_CLASS_DEF (binary_negate, <std::equal_to<int> >); |
| |
| TEST_FUNCTION_DEF ( |
| std::binary_negate<std::equal_to<int> > |
| std::not2 (const std::equal_to<int>&)); |
| |
| TEST_CLASS_DEF (binder1st, <std::plus<int> >); |
| |
| TEST_FUNCTION_DEF ( |
| std::binder1st<std::plus<int> > |
| std::bind1st (const std::plus<int>&, const int&)); |
| |
| TEST_CLASS_DEF (binder2nd , <std::plus<int> >); |
| |
| TEST_FUNCTION_DEF ( |
| std::binder2nd<std::plus<int> > |
| std::bind2nd (const std::plus<int>&, 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<int, void>::argument_type *argument = (int*)0; |
| std::unary_function<int, void>::result_type *result = (void*)0; |
| |
| std::binary_function<int, char, void>::first_argument_type *a1 = (int*)0; |
| std::binary_function<int, char, void>::second_argument_type *a2 = (char*)0; |
| std::binary_function<int, char, void>::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<N::fun::argument_type, \ |
| N::fun::result_type> *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<N::fun::first_argument_type, \ |
| N::fun::second_argument_type, \ |
| N::fun::result_type> *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<int>, +, 1, 2); |
| |
| // 20.3.2, p3 |
| TEST_BINARY_OP (minus<int>, -, 3, 2); |
| |
| // 20.3.2, p4 |
| TEST_BINARY_OP (multiplies<int>, *, 2, 3); |
| |
| // 20.3.2, p5 |
| TEST_BINARY_OP (divides<int>, /, 6, 3); |
| |
| // 20.3.2, p6 |
| TEST_BINARY_OP (modulus<int>, %, 7, 3); |
| |
| // 20.3.2, p7 |
| TEST_UNARY_OP (negate<int>, -, 1); |
| |
| // exercise extensions |
| |
| // tested fununctions are in a private namespace |
| #undef N |
| #define N _RW |
| |
| TEST_UNARY_OP (identity<int>, +, 3); |
| TEST_UNARY_OP (unary_plus<int>, +, 4); |
| TEST_UNARY_OP (bitwise_complement<int>, ~, 5); |
| |
| TEST_BINARY_OP (bitwise_and<int>, &, 0x0f, 0x05); |
| TEST_BINARY_OP (bitwise_or<int>, |, 0x0f, 0xf0); |
| TEST_BINARY_OP (exclusive_or<int>, ^, 0x0f, 0xf1); |
| |
| TEST_BINARY_OP (shift_left<int>, <<, 3, 3); |
| TEST_BINARY_OP (shift_right<int>, >>, 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<int>, ==, 1, 1); |
| TEST_BINARY_OP (equal_to<double>, ==, 1.0, 2.0); |
| |
| // 20.3.3, p3 |
| TEST_BINARY_OP (not_equal_to<int>, !=, 1, 1); |
| TEST_BINARY_OP (not_equal_to<double>, !=, 1.0, 2.0); |
| |
| // 20.3.3, p4 |
| TEST_BINARY_OP (greater<int>, >, 1, 1); |
| TEST_BINARY_OP (greater<double>, >, 2.0, 1.0); |
| |
| // 20.3.3, p5 |
| TEST_BINARY_OP (less<int>, <, 1, 1); |
| TEST_BINARY_OP (less<double>, <, 1.0, 2.0); |
| |
| // 20.3.3, p6 |
| TEST_BINARY_OP (greater_equal<int>, >=, 1, 1); |
| TEST_BINARY_OP (greater_equal<double>, >=, 1.0, 2.0); |
| |
| // 20.3.3, p7 |
| TEST_BINARY_OP (less_equal<int>, <=, 1, 1); |
| TEST_BINARY_OP (less_equal<double>, <=, 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<int>, &&, 0, 1); |
| TEST_BINARY_OP (logical_and<double>, &&, 1.0, 2.0); |
| |
| // 20.3.4, p3 |
| TEST_BINARY_OP (logical_or<char>, ||, '\0', '\0'); |
| TEST_BINARY_OP (logical_or<int>, ||, 0, 1); |
| TEST_BINARY_OP (logical_or<double>, ||, 1.0, 2.0); |
| |
| // 20.3.4, p4 |
| TEST_UNARY_OP (logical_not<int>, !, 0); |
| TEST_UNARY_OP (logical_not<double>, !, 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<std::logical_not<int> >&); |
| void is_explicit (const std::binary_negate<std::equal_to<int> >&); |
| void is_explicit (const std::pointer_to_unary_function<int, int>&); |
| void is_explicit (const std::pointer_to_binary_function<int, int, int>&); |
| |
| struct has_implicit_ctor |
| { |
| // NOT explicit |
| has_implicit_ctor (const std::logical_not<int>&) { } |
| has_implicit_ctor (const std::equal_to<int>&) { } |
| |
| 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<int>()); |
| |
| #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<int> > (std::logical_not<int> ()) |
| |
| // 20.3.5, p2 |
| TEST_UNARY_OP (unary_negate<std::logical_not<int> >, !!, 0); |
| TEST_UNARY_OP (unary_negate<std::logical_not<int> >, !!, 1); |
| |
| // exercise the convenience function template std::not1() |
| #undef CTOR_ARG_LIST |
| #define CTOR_ARG_LIST = std::not1 (std::logical_not<char> ()) |
| |
| // 20.3.5, p3 |
| TEST_UNARY_OP (unary_negate<std::logical_not<char> >, !!, '\0'); |
| TEST_UNARY_OP (unary_negate<std::logical_not<char> >, !!, '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<double> > (std::equal_to<double> ()) |
| |
| // 20.3.5, p4 |
| TEST_BINARY_OP (binary_negate<std::equal_to<double> >, !=, 0.0, 1.0); |
| TEST_BINARY_OP (binary_negate<std::equal_to<double> >, !=, 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<int> > (std::not_equal_to<int> ()) |
| |
| TEST_BINARY_OP (binary_negate<std::not_equal_to<int> >, ==, 0, 1); |
| TEST_BINARY_OP (binary_negate<std::not_equal_to<int> >, ==, 1, 2); |
| |
| // exercise the convenience function template std::not2() |
| #undef CTOR_ARG_LIST |
| #define CTOR_ARG_LIST = std::not2 (std::equal_to<int> ()) |
| |
| // 20.3.5, p5 |
| TEST_BINARY_OP (binary_negate<std::equal_to<int> >, !=, 2, 2); |
| TEST_BINARY_OP (binary_negate<std::equal_to<int> >, !=, 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<std::minus<int> > { |
| |
| binder1st_derivative () |
| : std::binder1st<std::minus<int> >(std::minus<int> (), 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<std::minus<int> > { |
| binder2nd_derivative () |
| : std::binder2nd<std::minus<int> >(std::minus<int> (), 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<int> 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<std::minus<int> >, 1 -, 0); |
| TEST_UNARY_OP (binder1st<std::minus<int> >, 1 -, 1); |
| |
| // 20.3.6.3, p1 and p2 |
| TEST_UNARY_OP (binder2nd<std::minus<int> >, -1 +, 0); |
| TEST_UNARY_OP (binder2nd<std::minus<int> >, 1 -, 1); |
| |
| // exercise the convenience function template std::bind1st<>() |
| #undef CTOR_ARG_LIST |
| #define CTOR_ARG_LIST = std::bind1st (std::divides<int>(), 6) |
| |
| // 20.3.6.2, p1 |
| TEST_UNARY_OP (binder1st<std::divides<int> >, 6 /, 3); |
| TEST_UNARY_OP (binder1st<std::divides<int> >, 6 /, 2); |
| |
| // exercise the convenience function template std::bind2nd<>() |
| #undef CTOR_ARG_LIST |
| #define CTOR_ARG_LIST = std::bind2nd (std::plus<int>(), -2) |
| |
| // 20.3.6.4, p1 |
| TEST_UNARY_OP (binder2nd<std::plus<int> >, -2 +, 0); |
| TEST_UNARY_OP (binder2nd<std::plus<int> >, -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<int, int> |
| |
| // 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<int, int, int> |
| |
| // 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<int, Integer>&); |
| |
| 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<int, Integer> |
| |
| 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<int, Integer, short> |
| |
| // 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, Integer> |
| |
| 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<int, Integer, short> |
| |
| // 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, Integer> |
| |
| 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<int, Integer, short> |
| |
| // 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, Integer> |
| |
| 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<int, Integer, short> |
| |
| // 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 */); |
| } |