blob: bcc37b8375daeda82196781533a476a9c8fc2d26 [file] [log] [blame]
/***************************************************************************
*
* 23.bitset.cpp - test exercising [lib.bitset]
*
* $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 2001-2006 Rogue Wave Software.
*
**************************************************************************/
#include <bitset>
#include <istream>
#include <ostream>
#include <cstdio> // for sprintf()
#include <climits>
#include <rw_char.h> // for UserChar
#include <rw_rand.h> // for rw_rand()
#include <driver.h> // for rw_test(), ...
#define NLOOPS 128
/**************************************************************************/
// sets the `n' least significant bits
std::size_t
bitmax (std::size_t n)
{
std::size_t result = 0;
while (n--)
result = result << 1 | 1U;
return result;
}
/**************************************************************************/
// fake bitset class, bit pattern represented as a character string
template <std::size_t N>
struct test_set
{
char bits_ [N + 1];
test_set () {
reset ();
bits_ [N] = '\0'; // null-terminate
}
_EXPLICIT test_set (unsigned long val) {
for (std::size_t i = 0; i != N; ++i)
set (i, !!(val & (1UL << i)));
bits_ [N] = '\0'; // NUL-terminate
}
_EXPLICIT test_set (const std::bitset<N> &rhs) {
for (std::size_t i = 0; i != N; ++i)
set (i, rhs.test (i));
bits_ [N] = '\0'; // NUL-terminate
}
// accessor function provided to work around
// a MIPSpro 7.3.1.1 bug (PR #25682)
const char* bits () const {
return bits_;
}
test_set& random () {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = char ('0' + rw_rand (2U));
return *this;
}
std::bitset<N> to_bitset () const {
std::bitset<N> tmp;
for (std::size_t i = 0; i != N; ++i)
tmp.set (i, test (i));
return tmp;
}
test_set& operator&= (const test_set &rhs) {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = '0' + ('1' == bits_ [i] && '1' == rhs.bits_ [i]);
return *this;
}
test_set& operator|= (const test_set &rhs) {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = '0' + ('1' == bits_ [i] || '1' == rhs.bits_ [i]);
return *this;
}
test_set& operator^= (const test_set &rhs) {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = '0' + !!(bits_ [i] - rhs.bits_ [i]);
return *this;
}
test_set& operator<<= (std::size_t n) {
for (std::size_t i = 0; i < N - n && i + n + 1 < N + 1; ++i)
bits_ [i] = bits_ [i + n];
for (std::size_t j = N - n; j != N; ++j)
bits_ [j] = '0';
return *this;
}
test_set& operator>>= (std::size_t n) {
for (std::size_t i = N - 1; i != n - 1; --i)
bits_ [i] = bits_ [i - n];
for (std::size_t j = n; j != 0; )
bits_ [--j] = '0';
return *this;
}
test_set& set () {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = '1';
return *this;
}
test_set& set (std::size_t pos, bool val) {
bits_ [N - pos - 1] = '0' + val;
return *this;
}
test_set& reset () {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = '0';
return *this;
}
test_set& reset (std::size_t pos) {
return bits_ [N - pos - 1] = '0', *this;
}
test_set operator~ () const {
return test_set (*this).flip ();
}
test_set& flip () {
for (std::size_t i = 0; i != N; ++i)
bits_ [i] = '0' + ('0' == bits_ [i]);
return *this;
}
test_set& flip (std::size_t pos) {
bits_ [N - pos - 1] = '0' + ('0' == bits_ [N - pos - 1]);
return *this;
}
std::size_t count () const {
std::size_t n = 0;
for (std::size_t i = 0; i != N; ++i)
n += bits_ [i] != '0';
return n;
}
bool operator== (const test_set &rhs) const {
for (std::size_t i = 0; i != N; ++i)
if (bits_ [i] != rhs.bits_ [i])
return false;
return true;
}
bool test (std::size_t pos) const {
return '0' != bits_ [N - pos - 1];
}
};
/**************************************************************************/
#ifndef _RWSTD_NO_EXPLICIT
// helper to verify that bitset ctor is explicit
// not defined since it must not be referenced if test is successful
// static commented out to prevent gcc warning: function declared
// 'static' but never defined
/* static */ void
is_explicit (const std::bitset<0>&);
struct has_implicit_ctor
{
// NOT explicit
has_implicit_ctor (const std::string&) { }
};
// calls to the overloaded is_explicit() resolve to the function below
static void
is_explicit (const has_implicit_ctor&) { }
#endif // _RWSTD_NO_EXPLICIT
static void
test_synopsis (std::bitset<0>*)
{
// prevent warnings about unreachable code
volatile bool dummy = false;
if (!dummy)
return;
typedef std::bitset<0> Bitset;
typedef Bitset::reference Reference;
Bitset::reference *pr = (Bitset::reference*)0;
_RWSTD_UNUSED (pr);
// verify that a member function is accessible and has the appropriate
// signature, including return type and exception specification
#define MEMFUN(result, name, arg_list) do { \
result (Bitset::reference::*pf) arg_list = &Bitset::reference::name; \
_RWSTD_UNUSED (pf); \
} while (0)
// exercise bitset::reference members
MEMFUN (Reference&, operator=, (bool));
MEMFUN (Reference&, operator=, (const Reference&));
MEMFUN (bool, operator~, () const);
MEMFUN (bool, operator bool, () const);
MEMFUN (Reference&, flip, ());
// 23.3.5.1 - verify bitset ctors
#if !defined (_RWSTD_NO_EXPLICIT) \
&& (!defined (__SUNPRO_CC) || __SUNPRO_CC > 0x530) \
&& (!defined (__GNUG__) || __GNUG__ >= 3)
// working around a SunPro 5.2 bug (see PR #25959)
// verify that bitset ctor is declared explicit
is_explicit (std::string ());
#endif // _RWSTD_NO_EXPLICIT && SunPro > 5.3
// verify default arguments
(void)Bitset (std::string ());
(void)Bitset (std::string (), std::string::size_type ());
// verify that a member function is accessible and has the appropriate
// signature, including return type and exception specification
#undef MEMFUN
#define MEMFUN(result, name, arg_list) do { \
result (Bitset::*pf) arg_list = &Bitset::name; \
_RWSTD_UNUSED (pf); \
} while (0)
MEMFUN (Bitset&, operator&=, (const Bitset&));
MEMFUN (Bitset&, operator|=, (const Bitset&));
MEMFUN (Bitset&, operator^=, (const Bitset&));
MEMFUN (Bitset&, operator<<=, (std::size_t));
MEMFUN (Bitset&, operator>>=, (std::size_t));
MEMFUN (Bitset&, set, ());
MEMFUN (Bitset&, set, (std::size_t, bool)); // lwg issue 186
Bitset ().set (0); // verify default argument
MEMFUN (Bitset&, reset, ());
MEMFUN (Bitset&, reset, (std::size_t));
MEMFUN (Bitset, operator~, () const);
MEMFUN (Bitset&, flip, ());
MEMFUN (Bitset&, flip, (std::size_t));
MEMFUN (Bitset::reference, operator[], (std::size_t));
MEMFUN (bool, operator[], (std::size_t) const);
MEMFUN (unsigned long, to_ulong, () const);
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
# if !defined (__HP_aCC) || __HP_aCC >= 60000
// working around HP aCC bugs PR #23312 and bug #503
# define PARAMLIST_3(T) T, std::char_traits<T>, std::allocator<T>
# define PARAMLIST_2(T) T, std::char_traits<T>
// exercise the overloaded member template function and ordinary
// member function to_string()
MEMFUN (std::basic_string<PARAMLIST_3 (char) >,
to_string<PARAMLIST_3 (char) >, (char, char) const);
MEMFUN (std::basic_string<PARAMLIST_3 (char) >,
to_string, (char, char) const);
# ifndef _RWSTD_NO_WCHAR_T
MEMFUN (std::basic_string<PARAMLIST_3 (wchar_t) >,
to_string<PARAMLIST_3 (wchar_t) >, (wchar_t, wchar_t) const);
# endif // _RWSTD_NO_WCHAR_T
MEMFUN (std::basic_string<PARAMLIST_3 (int) >,
to_string<PARAMLIST_3 (int) >, (int, int) const);
# undef PARAMLIST_3
# undef PARAMLIST_2
# endif // !__HP_aCC || __HP_aCC >= 60000
#endif // _RWSTD_NO_MEMBER_TEMPLATES
MEMFUN (std::size_t, size, () const);
MEMFUN (std::size_t, count, () const);
MEMFUN (bool, operator==, (const Bitset&) const);
MEMFUN (bool, operator!=, (const Bitset&) const);
MEMFUN (bool, test, (std::size_t) const);
MEMFUN (bool, any, () const);
MEMFUN (bool, none, () const);
MEMFUN (Bitset, operator>>, (std::size_t) const);
MEMFUN (Bitset, operator<<, (std::size_t) const);
#define FUN(result, name, arg_list) do { \
result (*pf) arg_list = &name; \
_RWSTD_UNUSED (pf); \
} while (0)
#if !defined (__IBMCPP__) || __IBMCPP__ > 502
FUN (Bitset, std::operator&, (const Bitset&, const Bitset&));
FUN (Bitset, std::operator|, (const Bitset&, const Bitset&));
FUN (Bitset, std::operator^, (const Bitset&, const Bitset&));
#else
// working around xlC 5.0.2.0 bug: PR #26561
FUN (Bitset, std::operator&,(const Bitset&,const Bitset&) _PTR_THROWS(()));
FUN (Bitset, std::operator|,(const Bitset&,const Bitset&) _PTR_THROWS(()));
FUN (Bitset, std::operator^,(const Bitset&,const Bitset&) _PTR_THROWS(()));
#endif
#define PARAMLIST(T) T, std::char_traits<T>
FUN (std::basic_istream< PARAMLIST (char) >&, std::operator>>,
(std::basic_istream< PARAMLIST (char) >&, Bitset&));
FUN (std::basic_ostream< PARAMLIST (char) >&, std::operator<<,
(std::basic_ostream< PARAMLIST (char) >&, const Bitset&));
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
# ifndef _RWSTD_NO_WCHAR_T
FUN (std::basic_istream< PARAMLIST (wchar_t) >&, std::operator>>,
(std::basic_istream< PARAMLIST (wchar_t) >&, Bitset&));
FUN (std::basic_ostream< PARAMLIST (wchar_t) >&, std::operator<<,
(std::basic_ostream< PARAMLIST (wchar_t) >&, const Bitset&));
# endif // _RWSTD_NO_WCHAR_T
# if !defined (_MSC_VER) || _MSC_VER > 1300
// MSVC is too dumb to handle bitset inserters and extractors
// parametrized on multiple template paramenters
FUN (std::basic_istream< PARAMLIST (int) >&, std::operator>>,
(std::basic_istream< PARAMLIST (int) >&, Bitset&));
FUN (std::basic_ostream< PARAMLIST (int) >&, std::operator<<,
(std::basic_ostream< PARAMLIST (int) >&, const Bitset&));
# endif // !defined (_MSC_VER) || _MSC_VER > 1300
#endif // _RWSTD_NO_MEMBER_TEMPLATES
#undef PARAMLIST
}
/**************************************************************************/
template <std::size_t N>
void test_ctors (const std::bitset<N>*)
{
const std::size_t bmask = ::bitmax (N);
{ // bitset::bitset()
rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset()", N);
const std::bitset<N> b;
rw_assert (0 == b.to_ulong (), 0, __LINE__,
"bitset<%d>::bitset ().to_ulong() == 0, got %#lx",
b.to_ulong ());
}
{ // bitset::bitset (unsigned long)
rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset (unsigned long)", N);
const std::bitset<N> b (ULONG_MAX & bmask);
rw_assert ((ULONG_MAX & bmask) == b.to_ulong (), 0, __LINE__,
"bitset<%d>::bitset (%#lx).to_ulong() == 0, got %#lx",
N, ULONG_MAX & bmask, b.to_ulong ());
}
{ // bitset (const string& str, size_t pos = 0, size_t n = (size_t)-1);
rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset (string)", N);
test_set<N> ts;
ts.set ();
_TRY {
const std::bitset<N> b = std::bitset<N>(std::string (ts.bits ()));
if (N <= sizeof (unsigned long) * CHAR_BIT)
rw_assert (b == bmask, 0, __LINE__,
"bitset<%d>::bitset(string(\"%s\").to_ulong()"
" == %#x, got %#x", N, ts.bits (), bmask,
b.to_ulong ());
else
rw_assert (test_set<N>(b) == ts, 0, __LINE__,
"bitset<%d>::bitset(string(\"111...111\")"
" == 111...111, got %s",
N, test_set<N>(b).bits ());
}
_CATCH (...) {
rw_assert (false, 0, __LINE__, (""));
}
}
{ // bitset (const bitset<N>& rhs)
rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset (const bitset&)", N);
const std::bitset<N> b1 (12345);
const std::bitset<N> b2 (b1);
rw_assert (b1.to_ulong () == b2.to_ulong (), 0, __LINE__,
"bitset<%d>::bitset (bitset<%d>(%#lx)).to_ulong() == %#lx,"
" got %#lx", N, b1.to_ulong (), b2.to_ulong ());
rw_info (0, 0, __LINE__,
"std::bitset<%d>::operator=(const bitset&)", N);
std::bitset<N> b3;
b3 = b1;
rw_assert (b1.to_ulong () == b3.to_ulong (), 0, __LINE__,
"bitset<%d>::bitset (bitset<%d>(%#lx)).to_ulong() == %#lx,"
" got %#lx", N, b1.to_ulong (), b3.to_ulong ());
}
}
/**************************************************************************/
template <std::size_t N>
void stress_ctors (const std::bitset<N>*)
{
rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset (string)", N);
const std::size_t max_mask = bitmax (N);
for (std::size_t i = 0; i != 1000U; i++) {
typedef unsigned long ULong;
// exercise 23.3.5.1, p2
const ULong n = ULong (rw_rand (0) & max_mask);
const std::bitset<N> b1 (n);
rw_assert (n == b1.to_ulong (), 0, __LINE__,
"bitset<%d>::bitset(%#lx).to_ulong() == %#lx, got %#lx",
N, n, n, b1.to_ulong ());
test_set<N> ts;
ts.random ();
// exercise 23.3.5.1, p3
std::bitset<N> b2 = std::bitset<N>(std::string (ts.bits ()));
rw_assert (test_set<N>(b2) == ts, 0, __LINE__,
"bitset<%d>::bitset (\"%s\") got %s",
N, ts.bits (), b2.to_string ().c_str ());
}
}
/**************************************************************************/
template <std::size_t N>
void test_operators (const std::bitset<N>*)
{
#define TEST_OP(op) do { \
rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator" #op \
"= (const bitset&)", N); \
\
test_set<N> lhs = test_set<N>().random (); \
const test_set<N> rhs = test_set<N>().random (); \
std::bitset<N> b_lhs = std::bitset<N>(std::string (lhs.bits ()));\
const std::bitset<N> b_rhs = std::bitset<N>(std::string (rhs.bits ()));\
const test_set<N> res = lhs op ## = rhs; \
const std::bitset<N> b_res = b_lhs op ## = b_rhs; \
\
rw_assert (res == test_set<N>(b_res), 0, __LINE__, \
"bitset<%lu>::operator" #op "= (const bitset<%lu>&):" \
" %s " #op " %s == %s, got %s", \
N, N, lhs.bits (), rhs.bits (), res.bits (), \
test_set<N>(b_res).bits ()); \
\
rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator" #op \
" (const bitset&)", N); \
lhs.random (); \
b_lhs = std::bitset<N>(std::string (lhs.bits ())); \
\
const test_set<N> res2 = lhs op ## = rhs; \
const std::bitset<N> b_res2 = b_lhs op b_rhs; \
\
rw_assert (res2 == test_set<N>(b_res2), 0, __LINE__, \
"bitset<%lu>::operator" #op " (const bitset<%lu>&):" \
" %s " #op " %s == %s, got %s", \
N, N, lhs.bits (), rhs.bits (), res2.bits (), \
test_set<N>(b_res2).bits ()); \
} while (0)
// prevent division by zero errors, also exercise shifting by
// N bits (operation must zero out the first operand)
// especially important is shifting bitset<N> by N bits where
// N >= sizeof (unsigned long) * CHAR_BIT, since this operation
// is undefined for unsigned longs but defined for bitset
const std::size_t M = N + 1;
for (int i = 0; i != NLOOPS; ++i) {
// 23.3.5.2, p1 and 23.3.5.3, p1
TEST_OP (&);
// 23.3.5.2, p3 and 23.3.5.3, p2
TEST_OP (|);
// 23.3.5.2, p5 and 23.3.5.3, p3
TEST_OP (^);
rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator<<=(size_t)", N);
const test_set<N> ts1 = test_set<N>().random ();
const test_set<N> ts2 = test_set<N>(ts1) <<= i % M;
std::bitset<N> b1 = std::bitset<N> (std::string (ts1.bits ()));
// 23.3.5.2, p7
b1 <<= i % M;
rw_assert (test_set<N>(b1) == ts2, 0, __LINE__,
"bitset<%d>::operator<<=(%lu): %s << %lu == %s, got %s",
N, i % M, ts1.bits (), i % M, ts2.bits (),
test_set<N>(b1).bits ());
rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator>>=(size_t)", N);
const test_set<N> ts3 = test_set<N>(ts1) >>= i % M;
std::bitset<N> b2 = std::bitset<N>(std::string (ts1.bits ()));
// 23.3.5.2, p9
b2 >>= i % M;
rw_assert (test_set<N>(b2) == ts3, 0, __LINE__,
"bitset<%d>::operator>>=(%lu): %s >> %lu == %s, got %s",
N, i % M, ts1.bits (), i % M, ts3.bits (),
test_set<N>(b2).bits ());
rw_info (!i, 0, __LINE__,
"std::bitset<%d>::operator<<=(size_t) (unused bits)", N);
if (N) {
b1.set (N - 1);
std::size_t first = b1.count ();
std::size_t second = (b1 <<= 1).count ();
rw_assert (!(first == second), 0, __LINE__,
"bitset<%lu>::operator<<=(1): "
"after <<= 1: expected %lu, got %lu",
N, first - 1, second);
}
rw_info (!i, 0, __LINE__,
"std::bitset<%d>::operator>>=(size_t) (unused bits)", N);
if (N) {
b2.set ();
std::size_t first = b2.count ();
std::size_t second = (b2 >>= 1).count ();
rw_assert (first - 1 == second, 0, __LINE__,
"bitset<%lu>::operator>>=(1): "
"after >>= 1: expected %lu, got %lu",
N, first - 1, second);
}
}
}
/**************************************************************************/
template <std::size_t N>
void test_other (const std::bitset<N>*)
{
for (std::size_t i = 0; i != NLOOPS; ++i) {
// 23.3.5.2, p23
test_set<N> ts1;
ts1.random ();
test_set<N> ts2 = ~ts1;
std::bitset<N> b1 = std::bitset<N>(std::string (ts1.bits ()));
std::bitset<N> b2 = ~b1;
rw_assert (ts2 == test_set<N>(b2), 0, __LINE__,
"bitset<%d>::operator~(): ~%s == %s, got %s",
N, ts1.bits (), ts2.bits (), test_set<N>(b2).bits ());
// 23.3.5.2, p25
b2.flip ();
rw_assert (ts1 == test_set<N>(b2), 0, __LINE__,
"bitset<%d>::flip (): ~%s == %s, got %s",
N, ts1.bits (), ts2.bits (), test_set<N>(b2).bits ());
// 23.3.5.2, p27
for (std::size_t _j = 0; _j != N; ++_j)
b2.flip (_j);
rw_assert (ts2 == test_set<N>(b2), 0, __LINE__,
"bitset<%d>::flip () == %s, got %s",
N, ts2.bits (), test_set<N>(b2).bits ());
// 23.3.5.3, p35
rw_assert (ts2.count () == b2.count (), 0, __LINE__,
"bitset<%d>::count () == %d, got %d [%s]",
N, ts2.count (), b2.count (), test_set<N>(b2).bits());
// 23.3.5.3, p37
rw_assert (b2 == b2 && (N && !(b1 == b2) || !N && b1 == b2),
0, __LINE__,
"bitset<%d>::operator==(const bitset<%ul>&) [%s]",
N, N, N ? test_set<N>(b2).bits () : "<empty>");
// 23.3.5.3, p38
rw_assert ((N && b1 != b2 || !N && !(b1 != b2)) && !(b2 != b2),
0, __LINE__,
"bitset<%d>::operator!=(const bitset<%ul>&) [%s]",
N, N, N ? test_set<N>(b2).bits () : "<empty>");
// 23.3.5.3, p42
rw_assert (b2.count() && b2.any() || !b2.count() && !b2.any(),
0, __LINE__,
"bitset<%d>::any () [%s]",
N, test_set<N>(b2).bits ());
// 23.3.5.3, p43
rw_assert (b2.count() && !b2.none() || !b2.count() && b2.none(),
0, __LINE__,
"bitset<%d>::none () [%s]",
N, test_set<N>(b2).bits ());
for (std::size_t k = 0; k != N; ++k) {
test_set<N> ts3 = test_set<N>(ts1) <<= k;
std::bitset<N> b3 = b1 << k;
rw_assert (test_set<N>(b3) == ts3, 0, __LINE__,
"bitset<%lu>::operator<<(%lu)", N, k);
ts3 = test_set<N>(ts1) >>= k;
b3 = b1 >> k;
rw_assert (test_set<N>(b3) == ts3, 0, __LINE__,
"bitset<%lu>::operator>>(%lu)", N, k);
}
}
}
/**************************************************************************/
template <std::size_t N>
void stress_count (const std::bitset<N>*)
{
rw_info (0, 0, __LINE__, "std::bitset<%lu>::count()", N);
for (std::size_t i = 0; i != N; i++) {
std::bitset<N> b;
for (std::size_t j = 0; j != i; j++)
b.set (j);
rw_assert (b.count () == i, 0, __LINE__,
"%lu. std::bitset<%lu>::count()", i, N);
}
}
/**************************************************************************/
template <std::size_t N>
void test_elem_access (const std::bitset<N>*)
{
rw_info (0, 0, __LINE__, "std::bitset<%lu>::test(size_t)", N);
rw_info (0, 0, __LINE__, "std::bitset<%lu>::operator[](size_t)", N);
rw_info (0, 0, __LINE__, "std::bitset<%lu>::operator[](size_t) const", N);
for (std::size_t i = 0; i != NLOOPS; ++i) {
const test_set<N> ts = test_set<N>().random ();
std::bitset<N> b = std::bitset<N>(std::string (ts.bits ()));
for (std::size_t _j = 0; _j != N; ++_j) {
// 23.3.5.2, p39
rw_assert (b.test (_j) == ts.test (_j), 0, __LINE__,
"bitset<%lu>::test (%lu): %s",
N, _j, test_set<N>(b).bits ());
// 23.3.5.2, p??: see lwg issue 11
rw_assert (b [_j] == ts.test (_j), 0, __LINE__,
"bitset<%lu>::operator[](%lu): %s",
N, _j, test_set<N>(b).bits ());
// 23.3.5.2, p??: see lwg issue 11
rw_assert (((const std::bitset<N>&)b) [_j] == ts.test (_j),
0, __LINE__,
"bitset<%lu>::operator[](%lu) const: %s",
N, _j, test_set<N>(b).bits ());
// exercise std::bitset<N>::reference
_TYPENAME std::bitset<N>::reference r = b [_j];
// std::bitset<N>::reference::flip()
r.flip ();
rw_assert (r == !ts.test (_j), 0, __LINE__,
"bitset<%lu>::reference::flip()", N);
// std::bitset<N>::reference::operator~()
bool toggled = ~r;
rw_assert (toggled == ts.test (_j), 0, __LINE__,
"bitset<%lu>::reference::operator~()", N);
// std::bitset<N>::reference::operator=(bool)
r = toggled;
rw_assert (r == ts.test (_j) && b.test (_j) == ts.test (_j),
0, __LINE__,
"bitset<%lu>::reference::operator=(bool)", N);
}
}
}
/**************************************************************************/
_RWSTD_NAMESPACE (std) {
_RWSTD_SPECIALIZED_CLASS
struct char_traits<UserChar>: UserTraits<UserChar> { };
} // namespace std
const char* type_name (char) { return "char"; }
#ifndef _RWSTD_NO_WCHAR_T
const char* type_name (wchar_t) { return "wchar_t"; }
#endif // _RWSTD_NO_WCHAR_T
const char* type_name (const UserChar&)
{
return "UserChar";
}
template <class charT>
const char* traits_name (const std::char_traits<charT>*)
{
static char name [64];
std::sprintf (name, "std::char_traits<%s>", type_name (charT ()));
return name;
}
const char* traits_name (const UserTraits<UserChar>*)
{
return "UserTraits";
}
template <class charT>
struct MyAlloc: std::allocator<charT> { };
template <class charT>
const char* alloc_name (const std::allocator<charT>&)
{
static char name [64];
std::sprintf (name, "std::allocator<%s>", type_name (charT ()));
return name;
}
template <class charT>
const char* alloc_name (const MyAlloc<charT>&)
{
static char name [64];
std::sprintf (name, "MyAlloc<%s>", type_name (charT ()));
return name;
}
template <class charT>
charT& assign (charT &lhs, char rhs)
{
return lhs = rhs;
}
UserChar& assign (UserChar &lhs, char rhs)
{
lhs.c = _RWSTD_STATIC_CAST (unsigned char, rhs);
return lhs;
}
// compare two strings, return the offset of the first mismatch
// or -1 when the strings are equal
template <class charT>
int compare (const charT str[], const char s[], const char bits [2])
{
const char* const beg = s;
for ( ; *s; ++s, ++str) {
if (*str != bits ['1' == *s])
return int (s - beg);
}
return *str ? s - beg : -1;
}
// compare two strings, return the offset of the first mismatch
// or -1 when the strings are equal
int compare (const UserChar str[], const char s[], const char bits [2])
{
const char* const beg = s;
for (; *s; ++s, ++str) {
if (char (str->c) != bits ['1' == *s])
return int (s - beg);
}
return str->c ? s - beg : -1;
}
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
// call the bitset<N>::to_string() member function template,
// explicitly specifying all three template arguments,
// and 2, 1, or 0 of the two default function arguments
template <std::size_t N, class charT, class Traits, class Alloc>
std::basic_string<charT, Traits, Alloc>
bitset_to_string_3 (const std::bitset<N> &bs, int nfargs,
charT zero, charT one,
std::basic_string<charT, Traits, Alloc>*)
{
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.template to_string<charT, Traits, Alloc>(zero);
case 0:
return bs.template to_string<charT, Traits, Alloc>();
}
return bs.template to_string<charT, Traits, Alloc>(zero, one);
}
template <std::size_t N, class Traits, class Alloc>
std::basic_string<UserChar, Traits, Alloc>
bitset_to_string_3 (const std::bitset<N> &bs, int nfargs,
UserChar zero, UserChar one,
std::basic_string<UserChar, Traits, Alloc>*)
{
// UserChar digits zero and one
static const UserChar dig[] = { { 0, '0' }, { 0, '1' } };
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.template to_string<UserChar, Traits, Alloc>(zero, dig [1]);
case 0:
return bs.template to_string<UserChar, Traits, Alloc>(dig [0], dig [1]);
}
return bs.template to_string<UserChar, Traits, Alloc>(zero, one);
}
// call the bitset<N>::to_string() member function template,
// explicitly specifying two of the three template arguments,
// and 2, 1, or 0 of the two default function arguments
template <std::size_t N, class charT, class Traits>
std::basic_string<charT, Traits, std::allocator<charT> >
bitset_to_string_2 (const std::bitset<N> &bs, int nfargs,
charT zero, charT one,
std::basic_string<charT, Traits,
std::allocator<charT> >*)
{
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.template to_string<charT, Traits>(zero);
case 0:
return bs.template to_string<charT, Traits>();
}
return bs.template to_string<charT, Traits>(zero, one);
}
template <std::size_t N, class Traits>
std::basic_string<UserChar, Traits, std::allocator<UserChar> >
bitset_to_string_2 (const std::bitset<N> &bs, int nfargs,
UserChar zero, UserChar one,
std::basic_string<UserChar, Traits,
std::allocator<UserChar> >*)
{
static const UserChar dig[] = { { 0, '0' }, { 0, '1' } };
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.template to_string<UserChar, Traits>(zero, dig [1]);
case 0:
return bs.template to_string<UserChar, Traits>(dig [0], dig [1]);
}
return bs.template to_string<UserChar, Traits>(zero, one);
}
// call the bitset<N>::to_string() member function template,
// explicitly specifying one of the three template arguments,
// and 2, 1, or 0 of the two default function arguments
template <std::size_t N, class charT>
std::basic_string<charT, std::char_traits<charT>, std::allocator<charT> >
bitset_to_string_1 (const std::bitset<N> &bs, int nfargs,
charT zero, charT one,
std::basic_string<charT,
std::char_traits<charT>,
std::allocator<charT> >*)
{
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.template to_string<charT>(zero);
case 0:
return bs.template to_string<charT>();
}
return bs.template to_string<charT>(zero, one);
}
template <std::size_t N>
std::basic_string<UserChar, std::char_traits<UserChar>,
std::allocator<UserChar> >
bitset_to_string_1 (const std::bitset<N> &bs, int nfargs,
UserChar zero, UserChar one,
std::basic_string<UserChar,
std::char_traits<UserChar>,
std::allocator<UserChar> >*)
{
// UserChar digits zero and one
static const UserChar dig[] = { { 0, '0' }, { 0, '1' } };
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.template to_string<UserChar>(zero, dig [1]);
case 0:
return bs.template to_string<UserChar>(dig [0], dig [1]);
}
return bs.template to_string<UserChar>(zero, one);
}
#endif // _RWSTD_NO_MEMBER_TEMPLATES
// call the bitset<N>::to_string() ordinary member function,
// explicitly specifying none of the three template arguments,
// and 2, 1, or 0 of the two default function arguments
template <std::size_t N>
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
bitset_to_string_0 (const std::bitset<N> &bs, int nfargs,
char zero, char one,
std::basic_string<char, std::char_traits<char>,
std::allocator<char> >*)
{
// invoke to_string with the number of function arguments specified
switch (nfargs) {
case 1:
return bs.to_string (zero);
case 0:
return bs.to_string ();
}
return bs.to_string (zero, one);
}
inline char to_char (char ch) { return ch; }
inline char to_char (UserChar ch) { return ch.c; }
#ifndef _RWSTD_NO_WCHAR_T
inline char to_char (wchar_t ch) { return char (ch); }
#endif // _RWSTD_NO_WCHAR_T
// convert a basic_string object to a tempstr object for diagnostics
template <class charT, class Traits, class Alloc>
std::string narrow_string (const std::basic_string<charT, Traits, Alloc> &str)
{
std::string res;
for (std::size_t i = 0; i != str.size (); ++i)
res += to_char (str [i]);
return res;
}
#define TO_STR(s) narrow_string (s).c_str ()
// convert an ordinary string to a tempstr object for diagnostics
// using the binary digits specified by `bits'
std::string to_string (const char *str, const char bits [2])
{
std::string res;
std::size_t i;
for (i = 0; str [i]; ++i)
res += bits ['1' == str [i]];
return res;
}
template <std::size_t N, class charT, class Traits, class Alloc>
void test_to_string (std::bitset<N>*, charT*, Traits*, Alloc*,
bool nontemplate_done)
{
static const char* const cname = type_name (charT ());
static const char* const tname = traits_name ((Traits*)0);
static const char* const aname = alloc_name (Alloc ());
rw_info (0, 0, __LINE__,
"std::bitset<%lu>::to_string<%s, %s, %s >()",
N, cname, tname, aname);
test_set<N> ts;
ts.random ();
const std::bitset<N> bs = ts.to_bitset ();
charT zero;
charT one;
assign (zero, 'o');
assign (one, 'x');
int pos;
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
////////////////////////////////////////////////////////////////////////
// exercise the overload of the to_string() member function template
// that takes all three template parameters different from char,
// char_traits<char>, and allocator<char>
typedef std::basic_string<charT, Traits, Alloc> String3;
String3 str3;
// specify none of the two function arguments (exercise defaults
// or the respective overloads)
str3 = bitset_to_string_3 (bs, 0, zero, one, (String3*)0);
pos = compare (str3.data (), ts.bits (), "01");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string () == \"%s\", got \"%s\": "
"mismatch at bit %d",
N, ts.bits (), TO_STR (str3), pos);
// specify one of the two function arguments (exercise the default
// or the respective overload)
rw_info (0, 0, __LINE__,
"std::bitset<%lu>::to_string<%s, %s, %s >(\"%s\")",
N, cname, tname, aname, cname);
str3 = bitset_to_string_3 (bs, 1, zero, one, (String3*)0);
pos = compare (str3.data (), ts.bits (), "o1");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "o1").c_str (),
TO_STR (str3), pos);
// specify both of the two function arguments
rw_info (0, 0, __LINE__,
"std::bitset<%lu>::to_string<%s, %s, %s >(%s, %s)",
N, cname, tname, aname, cname, cname);
str3 = bitset_to_string_3 (bs, 2, zero, one, (String3*)0);
pos = compare (str3.data (), ts.bits (), "ox");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o', 'x') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "ox").c_str (),
TO_STR (str3), pos);
////////////////////////////////////////////////////////////////////////
// exercise the overload of the to_string() member function template
// that takes the first two template parameters different from char,
// and char_traits<char>
rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string<%s, %s >()",
N, cname, tname);
typedef std::allocator<charT> CharTAlloc;
typedef std::basic_string<charT, Traits, CharTAlloc> String2;
String2 str2;
// specify none of the two function arguments (exercise defaults
// or the respective overloads)
str2 = bitset_to_string_2 (bs, 0, zero, one, (String2*)0);
pos = compare (str2.data (), ts.bits (), "01");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string () == %s, got %s: mismatch at bit %d",
N, ts.bits (), TO_STR (str2), pos);
// specify one of the two function arguments (exercise the default
// or the respective overload)
rw_info (0, 0, __LINE__,
"std::bitset<%lu>::to_string<%s, %s >(%s)",
N, cname, tname, cname);
str2 = bitset_to_string_2 (bs, 1, zero, one, (String2*)0);
pos = compare (str2.data (), ts.bits (), "o1");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "o1").c_str (),
TO_STR (str2), pos);
// specify both of the two function arguments
rw_info (0, 0, __LINE__,
"std::bitset<%lu>::to_string<%s, %s >(%s, %s)",
N, cname, tname, cname, cname);
str2 = bitset_to_string_2 (bs, 2, zero, one, (String2*)0);
pos = compare (str2.data (), ts.bits (), "ox");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o', 'x') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "ox").c_str (),
TO_STR (str2), pos);
////////////////////////////////////////////////////////////////////////
// exercise the overload of the to_string() member function template
// that takes the first template parameter different from char
rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string<%s>()",
N, cname);
typedef std::char_traits<charT> CharTraits;
typedef std::basic_string<charT, CharTraits, CharTAlloc> String1;
String1 str1;
// specify none of the two function arguments (exercise defaults
// or the respective overloads)
str1 = bitset_to_string_1 (bs, 0, zero, one, (String1*)0);
pos = compare (str1.data (), ts.bits (), "01");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string () == %s, got %s: mismatch at bit %d",
N, ts.bits (), TO_STR (str1), pos);
// specify one of the two function arguments (exercise the default
// or the respective overload)
rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string<%s>(%s)",
N, cname, cname);
str1 = bitset_to_string_1 (bs, 1, zero, one, (String1*)0);
pos = compare (str1.data (), ts.bits (), "o1");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "o1").c_str (),
TO_STR (str1), pos);
// specify both of the two function arguments
rw_info (0, 0, __LINE__,
"std::bitset<%lu>::to_string<%s>(%s, %s)",
N, cname, cname, cname);
str1 = bitset_to_string_1 (bs, 2, zero, one, (String1*)0);
pos = compare (str1.data (), ts.bits (), "ox");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o', 'x') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "ox").c_str (),
TO_STR (str1), pos);
#endif // _RWSTD_NO_MEMBER_TEMPLATES
////////////////////////////////////////////////////////////////////////
// exercise the non-template overload of the to_string() member
if (nontemplate_done)
return;
rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string ()", N);
typedef std::string String0;
String0 str0;
// specify none of the two function arguments (exercise defaults
// or the respective overloads)
str0 = bitset_to_string_0 (bs, 0, 'o', 'x', (String0*)0);
pos = compare (str0.data (), ts.bits (), "01");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string () == %s, got %s: mismatch at bit %d",
N, ts.bits (), str0.c_str (), pos);
// specify one of the two function arguments (exercise the default
// or the respective overload)
rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string (char)", N);
str0 = bitset_to_string_0 (bs, 1, 'o', 'x', (String0*)0);
pos = compare (str0.data (), ts.bits (), "o1");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "o1").c_str (),
str0.c_str (), pos);
// specify both of the two function arguments
rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string (char, char)", N);
str0 = bitset_to_string_0 (bs, 2, 'o', 'x', (String0*)0);
pos = compare (str0.data (), ts.bits (), "ox");
rw_assert (-1 == pos, 0, __LINE__,
"bitset<%lu>::to_string ('o', 'x') == %s, got %s: "
"mismatch at bit %d", N,
to_string (ts.bits (), "ox").c_str (),
str0.c_str (), pos);
}
template <std::size_t N>
void test_to_string (const std::bitset<N>*)
{
test_to_string ((std::bitset<N>*)0,
(char*)0,
(std::char_traits<char>*)0,
(std::allocator<char>*)0,
false);
#ifndef _RWSTD_NO_WCHAR_T
test_to_string ((std::bitset<N>*)0,
(wchar_t*)0,
(std::char_traits<wchar_t>*)0,
(std::allocator<wchar_t>*)0,
true);
#endif // _RWSTD_NO_WCHAR_T
test_to_string ((std::bitset<N>*)0,
(UserChar*)0,
(UserTraits<UserChar>*)0,
(std::allocator<UserChar>*)0,
true);
}
/**************************************************************************/
template <std::size_t N>
void run_test (const std::bitset<N>*)
{
test_ctors ((std::bitset<N>*)0);
stress_ctors ((std::bitset<N>*)0);
test_elem_access ((std::bitset<N>*)0);
test_operators ((std::bitset<N>*)0);
test_other ((std::bitset<N>*)0);
stress_count ((std::bitset<N>*)0);
test_to_string ((std::bitset<N>*)0);
}
/**************************************************************************/
static int
run_test (int, char**)
{
test_synopsis ((std::bitset<0>*)0);
#define DO_TEST(N) run_test ((std::bitset<N>*)0)
DO_TEST ( 0); // interesting case
DO_TEST ( 1); // interesting case
DO_TEST ( 2);
DO_TEST ( 31);
DO_TEST ( 32); // interesting case
DO_TEST ( 33); // interesting case
DO_TEST ( 34);
DO_TEST ( 63);
DO_TEST ( 64); // interesting case
DO_TEST ( 65); // interesting case
DO_TEST ( 66);
DO_TEST ( 123);
DO_TEST ( 127); // interesting case
DO_TEST ( 128); // interesting case
DO_TEST ( 129);
DO_TEST ( 130);
DO_TEST ( 255);
DO_TEST ( 256); // interesting case
#if !defined(_MSC_VER) || _MSC_VER != 1300
// FIXME: MSVC 514 can't compile bitset<257>!
DO_TEST ( 257); // interesting case
#endif
DO_TEST ( 258); // interesting case
DO_TEST ( 333);
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
// TODO: add command line options to control tested functionality
return rw_test (argc, argv, __FILE__,
"lib.bitset",
0 /* no comment */,
run_test,
"",
(void*)0 /* sentinel */);
}