first commit

This commit is contained in:
Jose Caban
2025-06-07 11:34:38 -04:00
commit 0eb2d7c07d
4708 changed files with 1500614 additions and 0 deletions

View File

@@ -0,0 +1,482 @@
/***************************************************************************
*
* 20.autoptr.cpp - test exercising [lib.auto.ptr]
*
* $Id: 20.auto.ptr.cpp 596356 2007-11-19 16:23:21Z faridz $
*
***************************************************************************
*
* 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-2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <rw/_defs.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// disable implicit inclusion to work around
// a limitation in IBM VisualAge 5.0.2.0 (see PR #26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
#include <memory>
/**************************************************************************/
#ifndef _RWSTD_EXPLICIT_INSTANTIATION
// explicitly instantiate
# if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD)
// verify that names are declared [only[ in namespace std
# define TEST_CLASS_DEF(name, Tparam) \
template class std::name Tparam \
/* 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)
# endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD
#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)
# else // if defined (_RWSTD_NO_NAMESPACE) || defined (_RWSTD_NO_HONOR_STD)
# define TEST_CLASS_DEF(name, ignore) void foo (void *name)
# endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD
#endif // _RWSTD_EXPLICIT_INSTANTIATION
// auto_ptr_ref instantiated first to prevent bogus MSVC 6.0 warning C4660:
// template-class specialization 'auto_ptr_ref<int>' is already instantiated
// follows lwg issue 127
TEST_CLASS_DEF (auto_ptr_ref, <int>);
TEST_CLASS_DEF (auto_ptr, <int>);
/**************************************************************************/
#include <cmdopt.h> // for rw_enabled()
#include <driver.h> // for rw_assert(), rw_test(), ...
/**************************************************************************/
struct Base
{
int i_; // unique object id
static int cnt_; // object counter
static int gen_; // unique id generator
Base (): i_ (gen_++) { ++cnt_; }
~Base () {
--cnt_;
}
static void sink (std::auto_ptr<Base>) { }
};
int Base::cnt_; // Base object counter
int Base::gen_; // Base unique id generator
struct Derived: Base
{
static std::auto_ptr<Derived> source () {
return std::auto_ptr<Derived> ();
}
static void sink (std::auto_ptr<Derived>) { }
};
// 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::auto_ptr<Base>&);
struct has_implicit_ctor
{
// NOT explicit
#ifndef _RWSTD_NO_NATIVE_BOOL
has_implicit_ctor (bool*) { }
#endif // _RWSTD_NO_NATIVE_BOOL
has_implicit_ctor (char*) { }
has_implicit_ctor (int*) { }
has_implicit_ctor (double*) { }
has_implicit_ctor (void**) { }
has_implicit_ctor (Base*) { }
};
void is_explicit (const has_implicit_ctor&) { }
template <class T>
void test_auto_ptr (T*, const char *tname)
{
rw_info (0, 0, 0, "std::auto_ptr<%s>", tname);
if (!rw_enabled (tname)) {
rw_note (0, 0, __LINE__, "auto_ptr<%s> test disabled", tname);
return;
}
// exercise 20.4.5, p2 - auto_ptr<> interface
typedef _TYPENAME std::auto_ptr<T>::element_type element_type;
// verify that element_type is the same as T
element_type *elem = (T*)0;
// verify that default ctor is explicit
is_explicit (elem);
// verify that a member function is accessible and has the appropriate
// signature, including return type and exception specification
#define FUN(result, T, name, arg_list) do { \
result (std::auto_ptr<T>::*pf) arg_list = &std::auto_ptr<T>::name; \
_RWSTD_UNUSED (pf); \
} while (0)
#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
// working around a bug in aCC (see PR #24430)
FUN (std::auto_ptr<T>&, T, operator=, (std::auto_ptr<T>&) _PTR_THROWS(()));
#endif // HP aCC > 5
FUN (T&, T, operator*, () const _PTR_THROWS (()));
#ifndef _RWSTD_NO_NONCLASS_ARROW_RETURN
FUN (T*, T, operator->, () const _PTR_THROWS (()));
#endif // _RWSTD_NO_NONCLASS_ARROW_RETURN
FUN (T*, T, get, () const _PTR_THROWS (()));
FUN (T*, T, release, () _PTR_THROWS (()));
FUN (void, T, reset, (T*) _PTR_THROWS (()));
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
# if !defined(__GNUG__) || __GNUG__ > 3 || __GNUG__ == 3 && __GNUC_MINOR__ > 2
// g++ 2.95.2 and HP aCC can't take the address of a template member
# if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
// SunPro incorrectly warns here (see PR #27276)
FUN (std::auto_ptr<Base>&, Base,
operator=, (std::auto_ptr<Derived>&) _PTR_THROWS (()));
// SunPro 5.4 can't decide between a ctor template
// and a conversion operator (see PR #24476)
# if !defined (__SUNPRO_CC) || __SUNPRO_CC > 0x540
# if !defined (_MSC_VER) || _MSC_VER > 1310 || defined (__INTEL_COMPILER)
FUN (std::auto_ptr_ref<Base>, Derived,
operator std::auto_ptr_ref<Base>, () _PTR_THROWS (()));
FUN (std::auto_ptr<Base>, Derived,
operator std::auto_ptr<Base>, () _PTR_THROWS (()));
# endif // MSVC > 7.1
# endif // SunPro > 5.4
# endif // HP aCC > 5
# endif // gcc > 3.2
#endif // _RWSTD_NO_MEMBER_TEMPLATES
rw_info (0, 0, 0, "[lib.auto.ptr.cons]");
T *pt = new T ();
// 20.4.5.1, p1
std::auto_ptr<T> ap1 (pt);
rw_assert (pt == ap1.get (), 0, __LINE__,
"auto_ptr<%s>::auto_ptr (%1$s*)", tname);
// 20.4.5.1, p2
std::auto_ptr<T> ap2 (ap1);
rw_assert (0 == ap1.get (), 0, __LINE__,
"auto_ptr<%s>::auto_ptr (auto_ptr&", tname);
rw_assert (pt == ap2.get (), 0, __LINE__,
"auto_ptr<%s>::auto_ptr (auto_ptr&)", tname);
// 20.4.5.1, p7, 8, 9
ap1 = ap2;
rw_assert (0 == ap2.get (), 0, __LINE__,
"auto_ptr<%s>::operator= (auto_ptr&)", tname);
rw_assert (pt == ap1.get (), 0, __LINE__,
"auto_ptr<%s>::operator= (auto_ptr&)", tname);
rw_info (0, 0, 0, "[lib.auto.ptr.members]");
// 20.4.5.2, p2
rw_assert (*ap1.get () == ap1.operator*(), 0, __LINE__,
"auto_ptr<%s>::operator*()", tname);
// 20.4.5.2, p3
rw_assert (ap1.get () == ap1.operator->(), 0, __LINE__,
"auto_ptr<%s>::operator->()", tname);
// 20.4.5.2, p4
rw_assert (pt == ap1.get (), 0, __LINE__,
"auto_ptr<%s>::get ()", tname);
// 20.4.5.2, p5, 6
rw_assert (pt == ap1.release () && 0 == ap1.get (), 0, __LINE__,
"auto_ptr<%s>::release ()", tname);
// 20.4.5.2, p7
ap1.reset (pt);
rw_assert (pt == ap1.get (), 0, __LINE__,
"auto_ptr<%s>::reset ()", tname);
}
/**************************************************************************/
static void
test_auto_ptr_void ()
{
// note that specializing auto_ptr on void is undefined
// due to 17.4.3.6, p2; this is an extension of this
// implementation
rw_info (0, 0, 0, "std::auto_ptr<void> [extension]");
std::auto_ptr<void> ap1;
std::auto_ptr<void> ap2 ((void*)0);
std::auto_ptr<void> ap3 (ap2);
ap1 = ap1;
ap1.operator= (ap1);
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
# if !defined (__HP_aCC) || 6 <= _RWSTD_HP_aCC_MAJOR
// working around an HP aCC 3 and 5 bug (STDCXX-655)
ap1.operator=<void>(ap1);
# endif // !HP aCC or HP aCC 6 and better
std::auto_ptr<int> ap4;
ap1 = ap4;
ap1.operator= (ap4);
ap1.operator=<int>(ap4);
#endif // _RWSTD_NO_MEMBER_TEMPLATES
// operator*() cannot be instantiated
void* pv;
pv = ap1.operator->();
pv = ap1.get ();
pv = ap1.release ();
ap1.reset ();
ap1.reset (pv);
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
# if !defined (__HP_aCC) || 6 <= _RWSTD_HP_aCC_MAJOR
// working around an HP aCC 3 and 5 bug (STDCXX-656)
const std::auto_ptr_ref<void> ar = ap1.operator std::auto_ptr_ref<void>();
const std::auto_ptr<void> ap5 = ap1.operator std::auto_ptr<void>();
_RWSTD_UNUSED (ar);
_RWSTD_UNUSED (ap5);
# endif // !HP aCC or HP aCC 6 and better
#endif // _RWSTD_NO_MEMBER_TEMPLATES
}
/**************************************************************************/
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
// exercise 20.4.5.4
static std::auto_ptr<Derived>
test_auto_ptr_conversions ()
{
rw_info (0, 0, 0, "[lib.auto.ptr.conv]");
// 20.4.5.1, p4, 5, 6
Derived *pd = new Derived;
std::auto_ptr<Derived> ap1 (pd);
rw_assert (pd == ap1.get (), 0, __LINE__,
"auto_ptr::auto_ptr ()");
std::auto_ptr<Base> ap2 (ap1);
rw_assert (0 == ap1.get (), 0, __LINE__,
"auto_ptr<Base>::auto_ptr(auto_ptr<Derived>&)");
rw_assert (_RWSTD_STATIC_CAST (Base*, pd) == ap2.get (), 0, __LINE__,
"auto_ptr<Base>::auto_ptr(auto_ptr<Derived>&)");
ap2.reset (pd);
// 20.4.5.2, p7 - must not delete owning pointer
ap2.reset (pd);
rw_assert (pd == ap2.get (), 0, __LINE__, "auto_ptr::reset ()");
pd = new Derived;
ap2.reset (pd); // must delete owning pointer
rw_assert (pd == ap2.get (), 0, __LINE__, "auto_ptr::reset ()");
// 20.4.5.3, p1, 2, 3 - creates an auto_ptr_ref
pd = new Derived;
std::auto_ptr<Base> ap3 =
std::auto_ptr<Base>(std::auto_ptr<Derived>(pd));
rw_assert ((Base*)pd == ap3.get (), 0, __LINE__,
"auto_ptr<>::auto_ptr(std::auto_ptr_ref)");
#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
pd = new Derived;
std::auto_ptr<Derived> ap4 (pd);
ap3 = std::auto_ptr<Base> (ap4);
rw_assert (0 == ap4.get () && (Base*)pd == ap3.get (), 0, __LINE__,
"auto_ptr<>::operator auto_ptr<>()");
#endif // HP aCC > 5
{
// see CWG issue 84 for some background on the sequence below
// http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#84
std::auto_ptr<Derived> pd1 (Derived::source ());
std::auto_ptr<Derived> pd2 (pd1);
#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
Derived::sink (Derived::source ());
#endif // HP aCC > 5
pd1 = pd2;
pd1 = Derived::source();
std::auto_ptr<Base> pb1 (Derived::source ());
std::auto_ptr<Base> pb2 (pd1);
// conversion sequence:
// 1. auto_ptr<Derived>::operator auto_ptr<Base>() [UDC]
// 2. auto_ptr<Base>::operator auto_ptr_ref<Base>() [UDC]
// 3. auto_ptr<Base>(auto_ptr_ref<Base>) [UDC]
// since the conversion sequence involves more than one UDC
// (User-Defined Conversion), it is illegal
// Base::sink (Derived::source ());
pb1 = pd2;
pb1 = Derived::source ();
return pd1;
}
}
#endif // _RWSTD_NO_MEMBER_TEMPLATES
/**************************************************************************/
static int rw_opt_no_conversions; // for --no-conversions
static int
run_test (int, char**)
{
#ifndef _RWSTD_NO_NATIVE_BOOL
test_auto_ptr ((bool*)0, "bool");
#endif // _RWSTD_NO_NATIVE_BOOL
test_auto_ptr ((char*)0, "char");
test_auto_ptr ((int*)0, "int");
test_auto_ptr ((double*)0, "double");
test_auto_ptr ((void**)0, "void*");
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
int count = Base::cnt_;
// exercise 20.4.5.4
if (rw_opt_no_conversions)
rw_note (0, 0, 0, "conversions test disabled");
else
test_auto_ptr_conversions ();
// verify that no objects leaked
rw_assert (count == Base::cnt_, 0, __LINE__,
"autoptr leaked %d objects", Base::cnt_ - count);
#endif // _RWSTD_NO_MEMBER_TEMPLATES
if (!rw_enabled ("void"))
rw_note (0, 0, 0, "auto_ptr<void> test disabled");
else
test_auto_ptr_void ();
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.auto.ptr",
0 /* no comment */,
run_test,
"|-no-conversions#",
&rw_opt_no_conversions,
(void*)0 /* sentinel */);
}

View File

@@ -0,0 +1,870 @@
/***************************************************************************
*
* 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 <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 */);
}

View File

@@ -0,0 +1,525 @@
/***************************************************************************
*
* 20.operators.cpp - test exercising [lib.operators]
*
* $Id: 20.operators.cpp 448928 2006-09-22 13:43:18Z faridz $
*
***************************************************************************
*
* 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 1994-2006 Rogue Wave Software.
*
**************************************************************************/
// The test exercises the ability to specialize various components of
// the library (algorithms and containers in particular) on user-defined
// iterator types in the presence of using directives.
#include <rw/_config.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// Disable implicit inclusion to work around
// a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
#if 0 // def _MSC_VER
// disabled (warnings may be meaningful)
# pragma warning (disable: 4800)
# pragma warning (disable: 4805)
#endif // _MSC_VER
#include <algorithm>
#include <deque>
#include <functional>
#include <iterator>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <utility>
#include <cstddef> // for std::size_t
#include <driver.h>
/**************************************************************************/
_USING (namespace std);
_USING (namespace std::rel_ops);
#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
// explicitly instantiate containers
template class
std::deque<int, std::allocator<int> >;
template class
std::list<int,std::allocator<int> >;
template class
std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >;
template class
std::set<int>;
template class
std::basic_string<int, std::char_traits<int>, std::allocator<int> >;
template class
std::vector<int, std::allocator<int> >;
#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
/**************************************************************************/
#if !defined (__SUNPRO_CC) || __SUNPRO_CC > 0x530
# define FUN(ignore, result, name, arg_list) do { \
result (*pf) arg_list = &name; \
_RWSTD_UNUSED (pf); \
} while (0)
#else
// working around a SunPro 5.3 bug (see PR #25972) that prevents it
// from taking the address of a function template in template code
# define FUN(T, result, name, arg_list) do { \
typedef typename T::iterator Iterator; \
typedef typename T::const_iterator ConstIterator; \
const Iterator *pi = 0; \
const ConstIterator *pci = 0; \
name (pi, pi); \
name (pci, pci); \
} while (0)
#endif // SunPro 5.3
#define TEST_INEQUALITY(T) \
FUN (T, bool, std::rel_ops::operator!=, \
(const T::iterator&, const T::iterator&)); \
FUN (T, bool, std::rel_ops::operator!=, \
(const T::const_iterator&, const T::const_iterator&))
#define TEST_OPERATORS(T) \
TEST_INEQUALITY (T); \
FUN (T, bool, std::rel_ops::operator>, \
(const T::iterator&, const T::iterator&)); \
FUN (T, bool, std::rel_ops::operator<=, \
(const T::iterator&, const T::iterator&)); \
FUN (T, bool, std::rel_ops::operator>=, \
(const T::iterator&, const T::iterator&)); \
FUN (T, bool, std::rel_ops::operator>, \
(const T::const_iterator&, const T::const_iterator&)); \
FUN (T, bool, std::rel_ops::operator<=, \
(const T::const_iterator&, const T::const_iterator&)); \
FUN (T, bool, std::rel_ops::operator>=, \
(const T::const_iterator&, const T::const_iterator&))
template <class Container, class RandomAccessIterator>
void test_iterator (Container, RandomAccessIterator)
{
TEST_OPERATORS (typename Container);
}
template <class Container>
void test_iterator (Container, int*)
{
// cannot specialize std::rel_ops::operators on native types
// or pointers to such things
}
/**************************************************************************/
template <class T>
struct UnaryPredicate
{
bool operator() (const T&) const {
return true;
}
};
template <class T>
struct BinaryPredicate
{
bool operator() (const T&, const T&) const {
return true;
}
};
template <class T>
struct RandomNumberGenerator
{
T operator() (int) const {
return T ();
}
};
template <class T>
struct Generator
{
T operator() () const {
return T ();
}
};
template <class T>
struct UnaryFunction
{
T operator() (const T &t) const {
return t;
}
};
template <class T>
struct BinaryFunction
{
T operator() (const T &t, const T&) const {
return t;
}
};
/**************************************************************************/
template <class T, class InputIterator>
void test_input_iterators (T, InputIterator)
{
// do not run (compile only), prevent warnings about unreachable code
static int count = 0;
if (++count)
return;
typedef InputIterator I;
std::for_each (I (), I (), UnaryFunction<T>());
std::find (I (), I (), T ());
std::find_if (I (), I (), UnaryPredicate<T>());
#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC
std::count (I (), I (), T ());
std::count_if (I (), I (), UnaryPredicate<T>());
#else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC)
std::size_t n = 0;
std::count (I (), I (), T (), n);
std::count_if (I (), I (), UnaryPredicate<T>(), n);
#endif // _RWSTD_NO_CLASS_PARTIAL_SPEC
std::mismatch (I (), I (), I ());
std::mismatch (I (), I (), I (), BinaryPredicate<T>());
std::equal (I (), I (), I ());
std::equal (I (), I (), I (), BinaryPredicate<T>());
std::includes (I (), I (), I (), I ());
std::includes (I (), I (), I (), I (), BinaryPredicate<T>());
std::lexicographical_compare (I (), I (), I (), I ());
std::lexicographical_compare (I (), I (), I (), I (), BinaryPredicate<T>());
}
/**************************************************************************/
template <class T, class OutputIterator>
void test_output_iterators (T, OutputIterator)
{
// do not run (compile only), prevent warnings about unreachable code
static int count = 0;
if (++count)
return;
typedef OutputIterator I;
std::copy (I (), I (), I ());
std::copy_backward (I (), I (), I ());
std::transform (I (), I (), I (), UnaryFunction<T>());
std::transform (I (), I (), I (), I (), BinaryFunction<T>());
std::replace_copy (I (), I (), I (), T (), T ());
std::replace_copy_if (I (), I (), I (), UnaryPredicate<T>(), T ());
std::merge (I (), I (), I (), I (), I ());
std::merge (I (), I (), I (), I (), I (), BinaryPredicate<T>());
std::set_union (I (), I (), I (), I (), I ());
std::set_union (I (), I (), I (), I (), I (), BinaryPredicate<T>());
std::set_intersection (I (), I (), I (), I (), I ());
std::set_intersection (I (), I (), I (), I (), I (), BinaryPredicate<T>());
std::set_difference (I (), I (), I (), I (), I ());
std::set_difference (I (), I (), I (), I (), I (), BinaryPredicate<T>());
std::set_symmetric_difference (I (), I (), I (), I (), I ());
std::set_symmetric_difference (I (), I (), I (), I (), I (),
BinaryPredicate<T>());
std::fill_n (I (), 0, T ());
std::generate_n (I (), 0, Generator<T>());
std::remove_copy (I (), I (), I (), T ());
std::remove_copy_if (I (), I (), I (), UnaryPredicate<T>());
std::unique_copy (I (), I (), I ());
std::unique_copy (I (), I (), I (), BinaryPredicate<T>());
std::reverse_copy (I (), I (), I ());
std::rotate_copy (I (), I (), I (), I ());
}
/**************************************************************************/
template <class T, class ForwardIterator>
void test_forward_iterators (T, ForwardIterator)
{
// do not run (compile only), prevent warnings about unreachable code
static int count = 0;
if (++count)
return;
typedef ForwardIterator I;
std::find_end (I (), I (), I (), I ());
std::find_end (I (), I (), I (), I (), BinaryPredicate<T>());
std::find_first_of (I (), I (), I (), I ());
std::find_first_of (I (), I (), I (), I (), BinaryPredicate<T>());
std::adjacent_find (I (), I ());
std::adjacent_find (I (), I (), BinaryPredicate<T>());
std::search (I (), I (), I (), I ());
std::search (I (), I (), I (), I (), BinaryPredicate<T>());
std::search_n (I (), I (), 0, T ());
std::search_n (I (), I (), 0, T (), BinaryPredicate<T>());
std::swap_ranges (I (), I (), I ());
std::iter_swap (I (), I ());
std::replace (I (), I (), T (), T ());
std::replace_if (I (), I (), UnaryPredicate<T>(), T ());
std::equal_range (I (), I (), T ());
std::equal_range (I (), I (), T (), BinaryPredicate<T>());
std::binary_search (I (), I (), T ());
std::binary_search (I (), I (), T (), BinaryPredicate<T>());
std::min_element (I (), I ());
std::min_element (I (), I (), BinaryPredicate<T>());
std::max_element (I (), I ());
std::max_element (I (), I (), BinaryPredicate<T>());
std::fill (I (), I (), T ());
std::generate (I (), I (), Generator<T>());
std::remove (I (), I (), T ());
std::remove_if (I (), I (), UnaryPredicate<T>());
std::unique (I (), I ());
std::unique (I (), I (), BinaryPredicate<T>());
std::reverse (I (), I ());
std::rotate (I (), I (), I ());
}
/**************************************************************************/
template <class T, class BidirectionalIterator>
void test_bidirectional_iterators (T, BidirectionalIterator)
{
// do not run (compile only), prevent warnings about unreachable code
static int count = 0;
if (++count)
return;
typedef BidirectionalIterator I;
std::partition (I (), I (), UnaryPredicate<T>());
std::stable_partition (I (), I (), UnaryPredicate<T>());
std::lower_bound (I (), I (), T ());
std::lower_bound (I (), I (), T (), BinaryPredicate<T>());
std::upper_bound (I (), I (), T ());
std::upper_bound (I (), I (), T (), BinaryPredicate<T>());
std::inplace_merge (I (), I (), I ());
std::inplace_merge (I (), I (), I (), BinaryPredicate<T>());
std::next_permutation (I (), I ());
std::next_permutation (I (), I (), BinaryPredicate<T>());
std::prev_permutation (I (), I ());
std::prev_permutation (I (), I (), BinaryPredicate<T>());
}
/**************************************************************************/
template <class T, class RandomAccessIterator>
void test_random_access_iterators (T, RandomAccessIterator)
{
// do not run (compile only), prevent warnings about unreachable code
static int count = 0;
if (++count)
return;
typedef RandomAccessIterator I;
RandomNumberGenerator<T> rndgen;
std::random_shuffle (I (), I ());
std::random_shuffle (I (), I (), rndgen);
std::sort (I (), I ());
std::sort (I (), I (), BinaryPredicate<T>());
std::stable_sort (I (), I ());
std::stable_sort (I (), I (), BinaryPredicate<T>());
std::partial_sort (I (), I (), I ());
std::partial_sort (I (), I (), I (), BinaryPredicate<T>());
std::partial_sort_copy (I (), I (), I (), I ());
std::partial_sort_copy (I (), I (), I (), I (), BinaryPredicate<T>());
std::nth_element (I (), I (), I ());
std::nth_element (I (), I (), I (), BinaryPredicate<T>());
std::push_heap (I (), I (), BinaryPredicate<T>());
std::pop_heap (I (), I (), BinaryPredicate<T>());
std::make_heap (I (), I (), BinaryPredicate<T>());
std::sort_heap (I (), I (), BinaryPredicate<T>());
}
/**************************************************************************/
static int
run_test (int, char**)
{
typedef std::map<int, int> Map;
typedef std::multimap<int, int> MultiMap;
// verify that rel_ops operators can be instantiated
// on iterators of the containers below
TEST_OPERATORS (std::deque<int>);
TEST_INEQUALITY (std::list<int>);
TEST_INEQUALITY (Map);
TEST_INEQUALITY (MultiMap);
TEST_INEQUALITY (std::set<int>);
TEST_INEQUALITY (std::multiset<int>);
#if !defined (_MSC_VER) || _MSC_VER > 1300
// prevent from testing with the braindead MSVC 6 and 7
// as a workaround for compiler bugs (PR #16828, 22268)
// prevent attempts to specialize rel_ops operators on
// native types (or pointers to such things)
test_iterator (std::basic_string<int>(),
std::basic_string<int>::iterator ());
test_iterator (std::vector<int>(),
std::vector<int>::iterator ());
#endif // MSVC > 7.0
TEST_OPERATORS (std::vector<bool>);
#define TEST_INPUT_ITERATORS(T) \
test_input_iterators (T (), std::deque<T>::iterator ()); \
test_input_iterators (T (), std::list<T>::iterator ()); \
test_input_iterators (std::map<T, T>::value_type (), \
std::map<T, T>::iterator ()); \
test_input_iterators (std::multimap<T, T>::value_type (), \
std::multimap<T, T>::iterator ()); \
test_input_iterators (T (), std::set<T>::iterator ()); \
test_input_iterators (T (), std::multiset<T, T>::iterator ()); \
test_input_iterators (T (), std::basic_string<T>::iterator ()); \
test_input_iterators (T (), std::vector<T>::iterator ())
#define TEST_OUTPUT_ITERATORS(T) \
test_output_iterators (T (), std::deque<T>::iterator ()); \
test_output_iterators (T (), std::list<T>::iterator ()); \
test_output_iterators (T (), std::basic_string<T>::iterator ()); \
test_output_iterators (T (), std::vector<T>::iterator ())
#define TEST_FORWARD_ITERATORS(T) \
test_forward_iterators (T (), std::deque<T>::iterator ()); \
test_forward_iterators (T (), std::list<T>::iterator ()); \
test_forward_iterators (T (), std::basic_string<T>::iterator ()); \
test_forward_iterators (T (), std::vector<T>::iterator ())
#define TEST_BIDIRECTIONAL_ITERATORS(T) \
test_bidirectional_iterators (T (), std::deque<T>::iterator ()); \
test_bidirectional_iterators (T (), std::list<T>::iterator ()); \
test_bidirectional_iterators (T (), std::basic_string<T>::iterator ()); \
test_bidirectional_iterators (T (), std::vector<T>::iterator ())
#define TEST_RANDOM_ACCESS_ITERATORS(T) \
test_random_access_iterators (T (), std::deque<T>::iterator ()); \
test_random_access_iterators (T (), std::basic_string<T>::iterator ()); \
test_random_access_iterators (T (), std::vector<T>::iterator ()); \
// verify that algorithms can be specialized on container
// iterators without causing ambiguities with rel_ops
TEST_INPUT_ITERATORS (int);
TEST_OUTPUT_ITERATORS (int);
TEST_FORWARD_ITERATORS (int);
TEST_BIDIRECTIONAL_ITERATORS (int);
TEST_RANDOM_ACCESS_ITERATORS (int);
#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MINOR > 3600
// working around an HP aCC bug (PR #28331)
TEST_INPUT_ITERATORS (bool);
TEST_OUTPUT_ITERATORS (bool);
TEST_FORWARD_ITERATORS (bool);
TEST_BIDIRECTIONAL_ITERATORS (bool);
TEST_RANDOM_ACCESS_ITERATORS (bool);
#endif // HP aCC > x.36
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.operators",
"interactions with the rest of the implementation",
run_test,
0 /* no command line options */);
}

View File

@@ -0,0 +1,297 @@
/***************************************************************************
*
* pairs.cpp - test exercising [lib.pairs]
*
* $Id: 20.pairs.cpp 550991 2007-06-26 23:58:07Z 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 2001-2006 Rogue Wave Software.
*
**************************************************************************/
#include <utility>
#include <alg_test.h>
#include <rw_value.h> // for UserClass
#include <driver.h>
/**************************************************************************/
struct Y: UserClass { };
int less_used;
_RWSTD_NAMESPACE (std) {
_RWSTD_SPECIALIZED_CLASS
bool less<Y>::operator() (const Y &a, const Y &b) const
{
++less_used;
return a < b;
}
} // namespace std
#ifndef _RWSTD_NO_EXPLICIT_CTOR_INSTANTIATION
typedef base<def_ctor> DefaultConstructible;
typedef base<cpy_ctor> CopyConstructible;
_RWSTD_NAMESPACE (std) {
// enclosing explicit instantiation within the declaring namespace
// instead of qualifying it with its name to work around compiler
// bugs (e.g., SunPro 5.4 -- see PR #28117)
#ifndef _RWSTD_NO_EMPTY_MEM_INITIALIZER
template pair<DefaultConstructible, DefaultConstructible>::pair ();
#endif // _RWSTD_NO_EMPTY_MEM_INITIALIZER
template pair<CopyConstructible, CopyConstructible>::
pair (const CopyConstructible&, const CopyConstructible&);
} // namespace std
#endif // _RWSTD_NO_EXPLICIT_CTOR_INSTANTIATION
/**************************************************************************/
template <class T, class U>
void test_pair (T, const char *tname, U, const char *uname)
{
typedef std::pair<T, U> Pair;
T *pt = (typename Pair::first_type*)0;
U *pu = (typename Pair::second_type*)0;
rw_info (0, 0, __LINE__, "std::pair<%s, %s> data members", tname, uname);
if (0) { // compile only
// verify pair data members and their types
Pair *p = 0;
pt = &p->first;
pu = &p->second;
_RWSTD_UNUSED (pt);
_RWSTD_UNUSED (pu);
}
if (0) { // compile only
Pair *p0 = 0;
std::pair<long, double> p1 (*p0);
_RWSTD_UNUSED (p1);
}
{
rw_info (0, 0, __LINE__, "std::pair<%s, %s>::pair()", tname, uname);
UserClass::reset_totals ();
std::pair<Y, Y> py;
rw_assert (UserClass::n_total_def_ctor_ == 2, 0, __LINE__,
"pair<Y, Y>::pair() called %d default ctors, "
"expected 2", UserClass::n_total_def_ctor_, 2);
#ifndef _RWSTD_NO_EMPTY_MEM_INITIALIZER
// exercise lwg issue 265
rw_assert (UserClass::n_total_copy_ctor_ == 0, 0, __LINE__,
"pair<Y, Y>::pair() called %d copy ctors, "
"expected 0", UserClass::n_total_copy_ctor_);
#else // if defined (_RWSTD_NO_EMPTY_MEM_INITIALIZER)
// 20.2.2, p2: commented out -- calls to copy ctor may be elided
// RW_ASSERT (t, UserClass::n_total_copy_ctor_ == 2,
// ("std::pair<Y, Y>::pair() called %d copy ctors, "
// "expected 2", UserClass::n_total_copy_ctor_));
#endif // _RWSTD_NO_EMPTY_MEM_INITIALIZER
rw_info (0, 0, __LINE__,
"std::pair<%s, %s>::pair(const %s&, const %s&)",
tname, uname, tname, uname);
UserClass x0;
UserClass x1;
UserClass::reset_totals ();
// 20.2.2, p3
std::pair<UserClass, UserClass> px0 (x0, x1);
rw_assert (UserClass::n_total_copy_ctor_ == 2, 0, __LINE__,
"pair<T, U>::pair (const T&, const U&) called %d cpy "
"ctors, expected 2", UserClass::n_total_copy_ctor_);
rw_info (0, 0, __LINE__,
"template <class T, class U> "
"std::pair<%s, %s>::pair(const pair<T, U>&)",
tname, uname);
UserClass::reset_totals ();
// 20.2.2, p4
std::pair<UserClass, UserClass> px (py);
rw_assert (UserClass::n_total_copy_ctor_ == 2, 0, __LINE__,
"template <class T, class U> pair<UserClass, "
"UserClass>::pair(const std::pair<T, U>&) called "
"%d cpy ctors, expected 2",
UserClass::n_total_copy_ctor_);
rw_info (0, 0, __LINE__,
"template <class T, class U> "
"std::pair<%s, %s>::operator= (const pair<T, U>&)",
tname, uname);
UserClass::reset_totals ();
// exercise template assignment if provided,
// otherwise template ctor and ordinary assignment
px = py;
rw_assert (UserClass::n_total_copy_ctor_ == 0, 0, __LINE__,
"template <class T, class U> pair<UserClass, "
"UserClass>::operator=(const pair<T, U>&) "
"called %d cpy ctors, expected 0",
UserClass::n_total_copy_ctor_);
rw_assert (UserClass::n_total_op_assign_ == 2, 0, __LINE__,
"template <class T, class U> pair<UserClass, "
"UserClass>::operator=(const pair<T, U>&) "
"called %d assignment operators, "
"expected 2", UserClass::n_total_op_assign_);
}
{
// exercise the signature of a nonmember (or static member) function
#define FUN(result, name, arg_list) do { \
rw_info (0, 0, __LINE__, "%s(const pair<%s, %s>&, " \
"const pair<%s, %s>&)", #name, \
tname, uname, tname, uname); \
/* make name unique to prevent bogus gcc -Wshadow warnings */ \
result (*_RWSTD_PASTE (pf, __LINE__)) arg_list = &name; \
_RWSTD_UNUSED (_RWSTD_PASTE (pf, __LINE__)); \
} while (0)
FUN (bool, std::operator==, (const Pair&, const Pair&));
FUN (bool, std::operator!=, (const Pair&, const Pair&));
FUN (bool, std::operator<, (const Pair&, const Pair&));
FUN (bool, std::operator<=, (const Pair&, const Pair&));
FUN (bool, std::operator>, (const Pair&, const Pair&));
FUN (bool, std::operator>=, (const Pair&, const Pair&));
// 20.2.2, p5
std::pair<Y, Y> p0;
Y::n_total_op_lt_ = 0;
bool b = p0 == p0;
rw_assert (b, 0, __LINE__,
"operator== (const pair<UserClass, UserClass>&, "
"const pair<UserClass, UserClass>&)");
rw_assert (2 == Y::n_total_op_eq_, 0, __LINE__,
"operator== (const pair<UserClass, UserClass>&, "
"const pair<UserClass, UserClass>&)");
// exercise lwg issue 348
// (std::less required to be used in order to satisfy 20.3.3, p8)
std::pair<Y, Y> p1;
p0.first.data_.val_ = 1;
p0.second.data_.val_ = 2;
p1.first.data_.val_ = 3;
p1.second.data_.val_ = 4;
less_used = 0;
b = p0 < p1;
rw_assert (b, 0, __LINE__,
"operator< (const pair<Y, Y>&, const pair<Y, Y>&)");
rw_assert (1 == less_used, 0, __LINE__,
"less<Y>::operator() called %d time(s), expected 1",
less_used);
p1.first.data_.val_ = 1;
less_used = 0;
b = p0 < p1;
rw_assert (b, 0, __LINE__,
"operator< (const pair<Y, Y>&, const pair<Y, Y>&)");
rw_assert (3 == less_used, 0, __LINE__,
"less<Y>::operator() called %d time(s), expected 3",
less_used);
p1.first.data_.val_ = 0;
less_used = 0;
b = p0 < p1;
rw_assert (!b, 0, __LINE__,
"operator< (const pair<Y, Y>&, const pair<Y, Y>&)");
rw_assert (2 == less_used, 0, __LINE__,
"less<Y>::operator() called %d time(s), expected 2",
less_used);
}
}
/**************************************************************************/
static int
run_test (int, char**)
{
test_pair (char (), "char", long (), "long");
test_pair (int (), "int", float (), "float");
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.pairs",
0 /* no comment */,
run_test,
"",
(void*)0 /* sentinel */);
}

View File

@@ -0,0 +1,430 @@
/***************************************************************************
*
* specialized.cpp - test exercising 20.4.4 [lib.specialized.algorithms]
*
* $Id: 20.specialized.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* 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 2001-2006 Rogue Wave Software.
*
**************************************************************************/
#include <memory>
#include <alg_test.h>
#include <driver.h>
/**************************************************************************/
#ifndef _RWSTD_NO_EXCEPTIONS
struct Y
{
static int count_;
static int ctor_;
static int dtor_;
static int throw_at_;
int val_;
Y (const Y &rhs) : val_ (rhs.val_) {
++ctor_;
if (count_ + 1 == throw_at_)
throw 0;
++count_;
}
Y (int val) : val_ (val) {
++ctor_;
if (count_ + 1 == throw_at_)
throw 0;
++count_;
}
~Y () {
++dtor_;
val_ = -2;
--count_;
}
private:
void operator= (const Y&); // not Assignable
};
int Y::count_;
int Y::ctor_;
int Y::dtor_;
int Y::throw_at_;
/**************************************************************************/
template <class T>
const char* type_name (volatile T*, T*) { return "volatile T*"; }
template <class T>
const char* type_name (const volatile T*, T*) { return "const volatile T*"; }
// defined as ordinary functions (as opposed to templates)
// to avoid tripping up broken compilers on argument deduction
inline const volatile int*
make_iter (const int *beg, const int*, const int*, const volatile int*)
{
return beg;
}
inline volatile Y*
make_iter (Y *beg, Y*, Y*, volatile Y*)
{
return beg;
}
/**************************************************************************/
// exercises uninitialized_copy [lib.uninitialized.copy]
// with emphasis on exception safety - the function is to have no effect
// if an exception is thrown
template <class InputIterator, class ForwardIterator>
void test_uninitialized_copy (const InputIterator &dummy,
const ForwardIterator*)
{
const char* const i1name = type_name (dummy, (int*)0);
const char* const i2name = type_name (ForwardIterator (), (Y*)0);
rw_info (0, 0, __LINE__, "std::uninitialized_copy(%s, %1$s, %s)",
i1name, i2name);
static const int a[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
const unsigned N = sizeof a / sizeof *a;
// allocate an uninitialized buffer
Y *buf = _RWSTD_STATIC_CAST (Y*, ::operator new (N * sizeof (Y)));
for (unsigned i = 0; i != N; ++i) {
Y::count_ = Y::ctor_ = Y::dtor_ = 0;
// throw during the copy construction of the i-th elem
Y::throw_at_ = i;
try {
// constructs i elements, the last ctor throws
const InputIterator first =
make_iter (a, a, a + i, dummy);
const InputIterator last =
make_iter (a + i, a, a + i, first);
const ForwardIterator result =
make_iter (buf, buf, buf + i, ForwardIterator ());
std::uninitialized_copy (first, last, result);
rw_assert (i == 0, 0, __LINE__,
"%zu. expected exception not thrown", i);
}
catch (int) {
// ctor throws an int, this is what's expected
}
catch (...) {
rw_assert (0, 0, __LINE__,
"%zu. exception of an unexpected type thrown", i);
}
// verify that all constructed elements were destroyed
rw_assert (Y::count_ == 0, 0, __LINE__,
"%zu. %d elements not destroyed", i, Y::count_);
// verify that the expected number of ctor and dtor calls were made
rw_assert (Y::ctor_ == Y::throw_at_, 0, __LINE__,
"%zu. %d ctor calls expected, got %d",
i, Y::throw_at_, Y::ctor_);
rw_assert (i ? Y::dtor_ + 1 == Y::throw_at_ : true, 0, __LINE__,
"%zu. %d dtor calls expected, got %d",
i, Y::throw_at_ - 1, Y::dtor_);
}
::operator delete (buf);
}
/**************************************************************************/
// exercises 20.4.4.2 and 3 - uninitialized_fill [lib.uninitialized.fill]
// and uninitialized_fill_n [lib.uninitialized.fill_n] with emphasis on
// exception safety - the function is to have no effect if an exception
// is thrown
template <class ForwardIterator>
void test_uninitialized_fill (const ForwardIterator*, bool test_count)
{
const char* const itname = type_name (ForwardIterator (), (Y*)0);
rw_info (0, 0, __LINE__,
"std::uninitialized_fill%{?}_n%{;}(%s, %{?}size_t%{:}%2$s%{;}, "
"const int&)", test_count, itname, test_count);
const unsigned N = 32;
// allocate an uninitialized buffer
Y *buf = _RWSTD_STATIC_CAST (Y*, ::operator new (N * sizeof (Y)));
for (unsigned i = 0; i != N; ++i) {
// prevent ctor below from throwing
Y::throw_at_ = -1;
// create a temporary and reset counters (in that order)
Y val (i);
Y::count_ = Y::ctor_ = Y::dtor_ = 0;
// throw during the copy construction of the i-th elem
Y::throw_at_ = i;
try {
// copy-constructs i elements, the last copy ctor throws
const ForwardIterator first =
make_iter (buf, buf, buf + i, ForwardIterator ());
if (test_count) {
std::uninitialized_fill_n (first, i, val);
}
else {
const ForwardIterator last =
make_iter (buf + i, buf, buf + i, first);
std::uninitialized_fill (first, last, val);
}
rw_assert (i == 0, 0, __LINE__,
"%zu. expected exception not thrown", i);
}
catch (int) {
// ctor throws an int, this is what's expected
}
catch (...) {
rw_assert (0, 0, __LINE__,
"%zu. exception of an unexpected type thrown", i);
}
// verify that all constructed elements were destroyed
rw_assert (Y::count_ == 0, 0, __LINE__,
"%zu. %d elements not destroyed", i, Y::count_);
// verify that the expected number of ctor and dtor calls were made
rw_assert (Y::ctor_ == Y::throw_at_, 0, __LINE__,
"%zu. %d ctor calls expected, got %d",
i, Y::throw_at_, Y::ctor_);
rw_assert (i ? Y::dtor_ + 1 == Y::throw_at_ : true, 0, __LINE__,
"%d. %d dtor calls expected, got %d",
i, Y::throw_at_ - 1, Y::dtor_);
}
::operator delete (buf);
}
/**************************************************************************/
int opt_copy;
int opt_fill;
int opt_fill_n;
int opt_input_iter;
int opt_fwd_iter;
int opt_bidir_iter;
int opt_rnd_iter;
int opt_volatile_ptr;
template <class InputIterator>
void test_uninitialized_copy (const InputIterator &dummy)
{
if (-1 < opt_fwd_iter)
test_uninitialized_copy (dummy, (FwdIter<Y>*)0);
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_copy (dummy, (BidirIter<Y>*)0);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_rnd_iter)
test_uninitialized_copy (dummy, (RandomAccessIter<Y>*)0);
else
rw_note (-1 > opt_rnd_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr) {
typedef volatile Y* VolatilePointer;
test_uninitialized_copy (dummy, (VolatilePointer*)0);
}
else
rw_note (-1 > opt_volatile_ptr--, 0, __LINE__,
"volatile T* tests disabled");
}
/**************************************************************************/
static int
run_test (int, char**)
{
typedef const volatile int* ConstVolatilePointer;
typedef /* */ volatile Y* VolatilePointer;
if (-1 < opt_copy) {
if (-1 < opt_input_iter)
test_uninitialized_copy (InputIter<int>(0, 0, 0));
else
rw_note (-1 > opt_input_iter--, 0, __LINE__,
"InputIterator tests disabled");
if (-1 < opt_fwd_iter)
test_uninitialized_copy (ConstFwdIter<int>());
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_copy (ConstBidirIter<int>());
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_rnd_iter)
test_uninitialized_copy (ConstRandomAccessIter<int>());
else
rw_note (-1 > opt_rnd_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr)
test_uninitialized_copy (ConstVolatilePointer ());
else
rw_note (-1 > opt_volatile_ptr--, 0, __LINE__,
"volatile T* tests disabled");
}
else
rw_note (0, 0, 0, "tests of std::uninitialized_copy disabled");
//////////////////////////////////////////////////////////////////
if (-1 < opt_fill) {
if (-1 < opt_fwd_iter)
test_uninitialized_fill ((FwdIter<Y>*)0, false);
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((BidirIter<Y>*)0, false);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((RandomAccessIter<Y>*)0, false);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr) {
test_uninitialized_fill ((VolatilePointer*)0, false);
}
else
rw_note (-1 > opt_volatile_ptr++,
0, 0, "volatile T* tests disabled");
}
else
rw_note (0, 0, 0, "tests of std::uninitialized_fill disabled");
//////////////////////////////////////////////////////////////////
if (-1 < opt_fill) {
if (-1 < opt_fwd_iter)
test_uninitialized_fill ((FwdIter<Y>*)0, true);
else
rw_note (-1 > opt_fwd_iter--, 0, __LINE__,
"ForwardIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((BidirIter<Y>*)0, true);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"BidirectionalIterator tests disabled");
if (-1 < opt_bidir_iter)
test_uninitialized_fill ((RandomAccessIter<Y>*)0, true);
else
rw_note (-1 > opt_bidir_iter--, 0, __LINE__,
"RandomAccessIterator tests disabled");
if (-1 < opt_volatile_ptr) {
test_uninitialized_fill ((VolatilePointer*)0, true);
}
else
rw_note (-1 > opt_volatile_ptr--, 0, __LINE__,
"volatile T* tests disabled");
}
else
rw_note (0, 0, 0, "tests of std::uninitialized_fill disabled");
return 0;
}
#else // _RWSTD_NO_EXCEPTIONS
static int
run_test (int, char**)
{
rw_note (0, 0, 0,
"exceptions disabled (_RWSTD_NO_EXCEPTIONS #defined), "
"cannot test");
return 0;
}
#endif // _RWSTD_NO_EXCEPTIONS
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.specialized.algorithms",
0 /* no comment */,
run_test,
"|-uninitialized_copy~ "
"|-uninitialized_fill~ "
"|-uninitialized_fill_n~ "
"|-InputIterator~ "
"|-ForwardIterator~ "
"|-BidirectionalIterator~ "
"|-RandomAccessIterator~ "
"|-volatile-pointer",
&opt_copy,
&opt_fill,
&opt_fill_n,
&opt_input_iter,
&opt_fwd_iter,
&opt_bidir_iter,
&opt_rnd_iter,
&opt_volatile_ptr);
}

View File

@@ -0,0 +1,492 @@
/***************************************************************************
*
* 20.temp.buffer.cpp - test exercising lib.temporary.buffer
*
* $Id: 20.temp.buffer.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* 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 2003-2006 Rogue Wave Software.
*
**************************************************************************/
#include <memory> // for get_temporary_buffer()
#include <cerrno> // for errno
#include <cstddef> // for ptrdiff_t, size_t
#include <cstdio> // for sprintf()
#include <cstring> // for memset()
#ifdef _MSC_VER
# include <climits> // for INT_MAX
# include <crtdbg.h> // for _CrtSetReportMode()
#endif
#include <rw_new.h>
#include <rw_printf.h>
#include <driver.h>
#ifndef _RWSTD_NO_SETRLIMIT
// #undef works around SunPro bug #568
# undef _TIME_T
# include <sys/resource.h> // for setrlimit()
# include <unistd.h> // for sbrk()
#endif // _RWSTD_NO_SETRLIMIT
#ifdef _AIX
// declare the loader symbol _edata defined by the AIX loader:
// The first address following the initialized data region.
extern "C" {
extern void* _edata;
} // extern "C"
#endif // _AIX
/**************************************************************************/
int compare (const void *beg, const void *end, int val)
{
typedef unsigned char UChar;
const UChar ucval = UChar (val);
for (const UChar *pc = (const UChar*)beg; pc != end; ++pc) {
if (*pc != ucval)
return *pc - ucval;
}
return 0;
}
/**************************************************************************/
template <class T>
void test_success (T*, const char *tname)
{
RW_ASSERT (0 != tname);
rw_info (0, 0, __LINE__, "std::get_temporary_buffer<%s>(ptrdiff_t)",
tname);
// verify that passing 0 as the argument either returns pair (0, 0)
// or pair (p, N) with p being a unique pointer in consecutive calls
// and N >= 0
static const unsigned pa_size = 32;
#ifndef __HP_aCC
std::pair<T*, std::ptrdiff_t> pa [pa_size];
#else // if defined (__HP_aCC)
// working around an HP aCC bug (PR #27302)
std::pair<T*, std::ptrdiff_t>* const pa =
new std::pair<T*, std::ptrdiff_t>[pa_size];
#endif // __HP_aCC
// establish a checkpoint for memory leaks
rwt_check_leaks (0, 0);
pa [0] = std::get_temporary_buffer<T>(0);
if (pa [0].first) {
std::memset (pa [0].first, ~0U, pa [0].second * sizeof (T));
pa [1] = std::get_temporary_buffer<T>(0);
if (pa [1].first)
std::memset (pa [1].first, ~1U, pa [1].second * sizeof (T));
rw_assert (pa [0].first != pa [1].first, 0, __LINE__,
"get_temporary_buffer<%s>(0).first not unique: "
"got %#p and %#p", tname, pa [0].first, pa [1].first);
}
else {
rw_assert (0 == pa [0].second, 0, __LINE__,
"get_temporary_buffer<%s>(0) == { 0, 0 }, got "
"{ %#p, %td }", tname, pa [0].first, pa [0].second);
}
pa [2] = std::get_temporary_buffer<T>(2);
rw_assert (0 != pa [2].first, 0, __LINE__,
"get_temporary_buffer<%s>(2).first != 0, got 0", tname);
if (0 == pa [2].first)
return;
std::memset (pa [2].first, ~2U, pa [2].second * sizeof (T));
rw_assert (2 <= pa [2].second, 0, __LINE__,
"get_temporary_buffer<%s>(2).second >= 2, got %td",
tname, pa [2].second);
pa [3] = std::get_temporary_buffer<T>(3);
rw_assert (0 != pa [3].first, 0, __LINE__,
"get_temporary_buffer<%s>(3).first != 0, got 0", tname);
if (!pa [3].first)
return;
rw_assert (3 <= pa [3].second, 0, __LINE__,
"get_temporary_buffer<%s>(3).second >= 3, got %td",
tname, pa [3].second);
// verify correct alignment (if the storage isn't properly aligned,
// expect SIGBUS on RISC machines, or SIGSEGV on HP-UX/PA-RISC)
pa [3].first [0] = T ();
pa [3].first [1] = T ();
pa [3].first [2] = T ();
std::memset (pa [3].first, ~3U, pa [3].second * sizeof (T));
// get the remaining temporary buffers and verify that they
// are each distinct from one another
for (unsigned i = 4; i != pa_size; ++i) {
const std::ptrdiff_t size =
std::ptrdiff_t (i % 2 ? i : _RWSTD_TMPBUF_SIZE + i);
pa [i] = std::get_temporary_buffer<T>(size);
if (pa [i].first)
std::memset (pa [i].first, ~i, pa [i].second * sizeof (T));
}
// verify the uniqueness of all ranges
for (unsigned i = 0; i < pa_size; ++i) {
for (unsigned j = 0; j < pa_size; ++j) {
const bool fail =
i != j && pa [i].first
&& pa [i].first >= pa [j].first
&& pa [i].first < pa [j].first + pa [j].second;
rw_assert (!fail, 0, __LINE__,
"pair { %#p, %td } returned from call %u overlaps "
"pair { %#p, %td } returned from call %u",
pa [i].first, pa [i].second, i,
pa [j].first, pa [j].second, j);
if (fail) {
// break out of both loops
i = j = unsigned (-1);
}
}
}
rw_info (0, 0, __LINE__,
"std::return_temporary_buffer<%s>(%1$s*)", tname);
// call return_temporary_buffer() on each returned pointer
// and verify that the contents of the buffers pointed to
// by all remaining unallocated pointers are unchanged
for (unsigned i = 0; i < pa_size; ++i) {
std::return_temporary_buffer (pa [i].first);
for (unsigned j = i + 1; j < pa_size; ++j) {
const bool success =
0 == compare (pa [j].first, pa [j].first + pa [j].second, ~j);
rw_assert (success, 0, __LINE__,
"return_temporary_buffer<%s>(%#p) corrupted "
"a buffer designated by { %#p %td }",
tname, pa [i].first, pa [j].first, pa [j].second);
if (!success) {
// break out of both loops
i = j = unsigned (-1);
}
}
}
std::size_t nbytes;
const std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
// verify the absence of memory leaks
rw_assert (!nblocks && !nbytes, 0, __LINE__,
"temporary buffer leaked %d bytes in %d blocks",
nbytes, nblocks);
#ifdef __HP_aCC
delete[] pa;
#endif // __HP_aCC
}
/**************************************************************************/
template <class T>
void test_failure (T*, const char *tname)
{
if (0 == tname) {
static char buf [40];
rw_sprintf (buf, "char[%zu]", sizeof (T));
tname = buf;
}
rw_info (0, 0, __LINE__,
"std::get_temporary_buffer<%s>(ptrdiff_t) on arithmetic overflow",
tname);
std::ptrdiff_t nelems = -1;
std::pair<T*, std::ptrdiff_t> pa;
pa = std::get_temporary_buffer<T>(nelems);
rw_assert (0 == pa.first && 0 == pa.second, 0, __LINE__,
"std::get_temporary_buffer<%s>(%td) == { 0, 0 }, "
"got { %#p, %td }",
tname, nelems, pa.first, pa.second);
for (std::size_t i = 2; i && i < sizeof (T); i <<= 1) {
// exercise arithmetic overflow (not to be confused
// with the out-of-memory tests below)
// attempts to allocate space for an array of elements
// with a total size that exceeds SIZE_MAX must fail
nelems = (_RWSTD_PTRDIFF_MAX / i) + 1;
pa = std::get_temporary_buffer<T>(nelems);
rw_assert (0 == pa.first && 0 == pa.second, 0, __LINE__,
"get_temporary_buffer<%s>(%ld) == { 0, 0 }, "
"got { %#p, %td }",
tname, nelems, pa.first, pa.second);
}
#ifndef _RWSTD_NO_SETRLIMIT
// exercise get_temporary_buffer in the presence of allocation
// failure (caused by setting the soft data limit to the current
// value)
// retrieve the current soft (rlim_cur) and hard (rlim_max) limits
struct rlimit rlim_old;
if (getrlimit (RLIMIT_DATA, &rlim_old)) {
rw_warn (0, 0, __LINE__,
"getrlimit(RLIMIT_DATA, { .rlim_max=%zu, .rlim_cur=%zu}) "
"failed: %{#m}: %m", rlim_old.rlim_max, rlim_old.rlim_cur);
return;
}
// set the soft limit to 0, leaving the hard limit unchanged
struct rlimit rlim_new = rlim_old;
#ifdef _AIX
{
// AIX setrlimit() fails to lower the limit for resource
// whose current usage is already higher than the new limit.
// Instead of setting the limit to 0, compute the current
// usage and use it to set the soft limit
const char* const brk_min = (char*)_edata;
const char* const brk_cur = (char*)sbrk (0);
rlim_new.rlim_cur = brk_cur - brk_min;
}
#else // if !defined (_AIX)
rlim_new.rlim_cur = 0;
#endif // _AIX
errno = 0;
// IEEE Std 1003.1, 2004 Edition (SUSv3):
// RLIMIT_DATA
// ...is the maximum size of a process' data segment, in bytes.
// If this limit is exceeded, the malloc() function shall fail
// with errno set to [ENOMEM].
if (setrlimit (RLIMIT_DATA, &rlim_new)) {
rw_warn (0, 0, __LINE__,
"setrlimit(RLIMIT_DATA, { .rlim_max=%zu, .rlim_cur=%zu}) "
"failed to lower the soft limit: %{#m}: %m",
rlim_new.rlim_max, rlim_new.rlim_cur);
return;
}
std::size_t nbytes = rlim_old.rlim_max;
#if 0 < _RWSTD_TMPBUF_SIZE
// make sure the size is larger than the size of the temp buff
if (nbytes <= _RWSTD_TMPBUF_SIZE)
nbytes = _RWSTD_TMPBUF_SIZE + 1;
#else // if _RWSTD_TMPBUF_SIZE <= 0
nbytes = 65536;
#endif // _RWSTD_TMPBUF_SIZE
if (nbytes < _RWSTD_SIZE_MAX)
++nbytes;
if (nbytes <= std::size_t (_RWSTD_PTRDIFF_MAX))
nelems = std::ptrdiff_t (nbytes);
else
nelems = _RWSTD_PTRDIFF_MAX;
nelems /= sizeof (T);
// retrieve the current limit just to show it in the info message
// ignore any errors
getrlimit (RLIMIT_DATA, &rlim_new);
rw_info (0, 0, __LINE__,
"std::get_temporary_buffer<%s>(%td) in low memory conditions "
": { .rlim_max = %zu, .rlim_cur = %zu }",
tname, nelems, rlim_new.rlim_max, rlim_new.rlim_cur);
// expect the function to fail
pa = std::get_temporary_buffer<T>(nelems);
// reset the soft limit to the original value (do it before any
// test output in case memory needs to be allocated during the
// output)
if (setrlimit (RLIMIT_DATA, &rlim_old)) {
rw_warn (0, 0, __LINE__,
"setrlimit(RLIMIT_DATA, { .rlim_max=%zu, .rlim_cur=%zu }) "
"failed to restore the soft limit: %{#m}: %m",
rlim_old.rlim_max, rlim_old.rlim_cur);
}
rw_assert (0 == pa.first && 0 == pa.second, 0, __LINE__,
"get_temporary_buffer<%s>(%td) == { 0, 0 } "
"in low memory conditions, got { %#p, %td }",
tname, nbytes, pa.first, pa.second);
#endif // _RWSTD_NO_SETRLIMIT
}
/**************************************************************************/
typedef void (*FunctionPointer)();
struct MyStruct { };
typedef void (MyStruct::*MemberPointer)();
template <std::size_t N>
struct BigStruct { char dummy [N]; };
/**************************************************************************/
template <class T>
void test_get_temporary_buffer (T *dummy, const char *tname)
{
RW_ASSERT (0 != tname);
test_success (dummy, tname);
test_failure (dummy, tname);
}
/**************************************************************************/
static int
run_test (int, char**)
{
test_get_temporary_buffer ((char*)0, "char");
test_get_temporary_buffer ((int*)0, "int");
#ifdef _RWSTD_LONG_LONG
test_get_temporary_buffer ((_RWSTD_LONG_LONG*)0, "long long");
#else // if !defined (_RWSTD_LONG_LONG)
test_get_temporary_buffer ((long*)0, "long");
#endif // _RWSTD_LONG_LONG
#ifndef _RWSTD_NO_LONG_DOUBLE
test_get_temporary_buffer ((long double*)0, "long double");
#else // if defined (_RWSTD_NO_LONG_DOUBLE)
test_get_temporary_buffer ((double*)0, "double");
#endif // _RWSTD_NO_LONG_DOUBLE
// exercise ordinary pointers
test_get_temporary_buffer ((void**)0, "void*");
// exercise function pointers
test_get_temporary_buffer ((FunctionPointer*)0, "void (*)()");
// exercise pointers to members
test_get_temporary_buffer ((MemberPointer*)0, "void (struct::*)()");
#if (!defined (__IBMCPP__) || __IBMCPP__ > 700) \
&& !defined (__HP_aCC)
# ifndef _MSC_VER
const std::size_t MAX_SIZE = _RWSTD_PTRDIFF_MAX;
# else
// the MSVC and ICC/Windows has maximum size of
// the array equal to 0x7fffffff bytes
const std::size_t MAX_SIZE = INT_MAX;
# endif
// avoid instantiating test on very large structs
// to prevent failures (at compile or run-time) due
// to compiler bugs
test_failure ((BigStruct<MAX_SIZE / 2>*)0, 0);
test_failure ((BigStruct<MAX_SIZE - 1>*)0, 0);
test_failure ((BigStruct<MAX_SIZE>*)0, 0);
#else
// work around VAC++ 7.0 (and prior) bug #549
// work around HP aCC 3,5,6 bug #565
rw_warn (0, 0, __LINE__, "get_temp_buffer<large-struct>() "
"not tested due to a compiler bug");
#endif // VAC++ > 7.0
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
#ifdef _MSC_VER
// disable "Invalid allocation size: 4294967292 bytes"
// message box from malloc()
_CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif
return rw_test (argc, argv, __FILE__,
"lib.temporary.buffer",
0 /* no comment */,
run_test,
"",
(void*)0 /* sentinel */);
}

View File

@@ -0,0 +1,251 @@
/***************************************************************************
*
* 20.temp.buffer.mt.cpp - test exercising the thread safety
* of std::get_temporary_buffer() and
* std::return_temporary_buffer()
*
* $Id: 20.temp.buffer.mt.cpp 650350 2008-04-22 01:35:17Z 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 2005-2008 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <memory> // for get_temporary_buffer
#include <utility> // for pair
#include <cassert> // for assert
#include <cstddef> // for ptrdiff_t
#include <cstdio> // for printf()
#include <cstring> // for memset()
#include <driver.h> // for rw_test(), ...
#include <rw_thread.h> // for rw_thread_create(), ...
/**************************************************************************/
#ifndef _RWSTD_REENTRANT
# define MAX_THREADS 0
#else
# define MAX_THREADS 32
#endif
/* extern */ unsigned rw_opt_nthreads = 4 <= MAX_THREADS ? 4 : MAX_THREADS;
/* extern */ unsigned rw_opt_nloops = 1024 * 1024;
/**************************************************************************/
struct thr_args
{
unsigned threadno_; // thread ordinal number
unsigned ngets_; // number of calls to get_temporary_buffer
unsigned nreturns_; // number of calls to return_temporary_buffer
};
/**************************************************************************/
template <class T>
std::pair<T*, std::ptrdiff_t>
test_get_buffer (thr_args *args, T*, unsigned nobjs)
{
++args->ngets_;
std::pair<T*, std::ptrdiff_t> buf =
std::get_temporary_buffer<T>(std::ptrdiff_t (nobjs));
// std::printf ("T%u: get %s: { %p, %d } == %u\n",
// args->threadno_, type_name (T ()),
// buf.first, buf.second, buf.second * sizeof (T));
if (buf.first && buf.second) {
const std::size_t nbytes = buf.second * sizeof (T);
std::memset (buf.first, args->threadno_ + 1, nbytes);
*((char*)buf.first + nbytes - 1) = '\0';
}
return buf;
}
/**************************************************************************/
template <class T>
void
test_return_buffer (thr_args *args, std::pair<T*, std::ptrdiff_t> &buf)
{
++args->nreturns_;
std::size_t len = 0;
if (buf.first) {
typedef unsigned char UChar;
for (const UChar *pb = (const UChar*)buf.first; ; ++pb, ++len) {
if (*pb != (args->threadno_ + 1)) {
if (0 == *pb)
++len;
break;
}
}
}
// std::printf ("T%u: return %s: { %p, %d } == %u\n",
// args->threadno_, type_name (T ()),
// buf.first, buf.second, len);
assert (len == buf.second * sizeof (T));
std::return_temporary_buffer<T>(buf.first);
buf.first = 0;
}
/**************************************************************************/
extern "C" void* thr_func (void *arg)
{
thr_args* const targs = (thr_args*)arg;
std::printf ("thread %u starting...\n", targs->threadno_);
#ifndef _RWSTD_INT64_T
typedef char Type64 [8];
#else // if defined (_RWSTD_INT64_T)
typedef _RWSTD_INT64_T Type64;
#endif // _RWSTD_INT64_T
std::pair<_RWSTD_INT8_T*, std::ptrdiff_t> buf0;
std::pair<_RWSTD_INT16_T*, std::ptrdiff_t> buf1;
std::pair<_RWSTD_INT32_T*, std::ptrdiff_t> buf2;
std::pair<Type64*, std::ptrdiff_t> buf3;
for (unsigned i = 0; i != rw_opt_nloops; ++i) {
const unsigned nelems = (i + targs->threadno_) % 32;
switch ((i + targs->threadno_) % 8) {
case 0:
buf0 = test_get_buffer (targs, (_RWSTD_INT8_T*)0, nelems);
break;
case 1:
buf1 = test_get_buffer (targs, (_RWSTD_INT16_T*)0, nelems);
break;
case 2:
buf2 = test_get_buffer (targs, (_RWSTD_INT32_T*)0, nelems);
break;
case 3:
buf3 = test_get_buffer (targs, (Type64*)0, nelems);
break;
case 4:
test_return_buffer (targs, buf0);
break;
case 5:
test_return_buffer (targs, buf2);
break;
case 6:
test_return_buffer (targs, buf1);
break;
case 7:
test_return_buffer (targs, buf3);
break;
}
}
// free any buffers that remain allocated
if (buf0.first) test_return_buffer (targs, buf0);
if (buf1.first) test_return_buffer (targs, buf1);
if (buf2.first) test_return_buffer (targs, buf2);
if (buf3.first) test_return_buffer (targs, buf3);
return 0;
}
/**************************************************************************/
static int
run_test (int, char*[])
{
rw_info (0, 0, 0, "std::get_temporary_buffer(ptrdiff_t)");
rw_info (0, 0, 0, "std::return_temporary_buffer(ptrdiff_t)");
if (0 < rw_opt_nthreads) {
rw_thread_t tid [MAX_THREADS + 1];
thr_args targs [MAX_THREADS + 1];
std::memset (targs, 0, sizeof targs);
for (unsigned i = 0; i != rw_opt_nthreads; ++i) {
targs [i].threadno_ = i;
rw_fatal (0 == rw_thread_create (tid + i, 0, thr_func, targs + i),
0, 0, "thread_create() failed");
}
for (unsigned i = 0; i != rw_opt_nthreads; ++i) {
rw_error (0 == rw_thread_join (tid [i], 0), 0, 0,
"thread_join() failed");
}
}
else {
thr_args targs;
std::memset (&targs, 0, sizeof targs);
thr_func (&targs);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.temporary.buffer",
0 /* no comment */,
run_test,
"|-nloops#0 " // must be non-negative
"|-nthreads#0-*", // must be in specified range
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads);
}