/*************************************************************************** * * 23.bitset.cpp - test exercising [lib.bitset] * * $Id: 23.bitset.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 2001-2006 Rogue Wave Software. * **************************************************************************/ #include #include #include #include // for sprintf() #include #include // for UserChar #include // for rw_rand() #include // 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 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 &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 to_bitset () const { std::bitset 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, std::allocator # define PARAMLIST_2(T) T, std::char_traits // exercise the overloaded member template function and ordinary // member function to_string() MEMFUN (std::basic_string, to_string, (char, char) const); MEMFUN (std::basic_string, to_string, (char, char) const); # ifndef _RWSTD_NO_WCHAR_T MEMFUN (std::basic_string, to_string, (wchar_t, wchar_t) const); # endif // _RWSTD_NO_WCHAR_T MEMFUN (std::basic_string, to_string, (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 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 void test_ctors (const std::bitset*) { typedef unsigned long ULong; const ULong bmask = ULong (::bitmax (N)); { // bitset::bitset() rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset()", N); const std::bitset 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 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 ts; ts.set (); _TRY { const std::bitset b = std::bitset(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(b) == ts, 0, __LINE__, "bitset<%d>::bitset(string(\"111...111\")" " == 111...111, got %s", N, test_set(b).bits ()); } _CATCH (...) { rw_assert (false, 0, __LINE__, ("")); } } { // bitset (const bitset& rhs) rw_info (0, 0, __LINE__, "std::bitset<%d>::bitset (const bitset&)", N); const std::bitset b1 (12345); const std::bitset 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 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 void stress_ctors (const std::bitset*) { 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 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 ts; ts.random (); // exercise 23.3.5.1, p3 std::bitset b2 = std::bitset(std::string (ts.bits ())); rw_assert (test_set(b2) == ts, 0, __LINE__, "bitset<%d>::bitset (\"%s\") got %s", N, ts.bits (), b2.to_string ().c_str ()); } } /**************************************************************************/ template void test_operators (const std::bitset*) { #define TEST_OP(op) do { \ rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator" #op \ "= (const bitset&)", N); \ \ test_set lhs = test_set().random (); \ const test_set rhs = test_set().random (); \ std::bitset b_lhs = std::bitset(std::string (lhs.bits ()));\ const std::bitset b_rhs = std::bitset(std::string (rhs.bits ()));\ const test_set res = lhs op ## = rhs; \ const std::bitset b_res = b_lhs op ## = b_rhs; \ \ rw_assert (res == test_set(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(b_res).bits ()); \ \ rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator" #op \ " (const bitset&)", N); \ lhs.random (); \ b_lhs = std::bitset(std::string (lhs.bits ())); \ \ const test_set res2 = lhs op ## = rhs; \ const std::bitset b_res2 = b_lhs op b_rhs; \ \ rw_assert (res2 == test_set(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(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 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 ts1 = test_set().random (); const test_set ts2 = test_set(ts1) <<= i % M; std::bitset b1 = std::bitset (std::string (ts1.bits ())); // 23.3.5.2, p7 b1 <<= i % M; rw_assert (test_set(b1) == ts2, 0, __LINE__, "bitset<%d>::operator<<=(%lu): %s << %lu == %s, got %s", N, i % M, ts1.bits (), i % M, ts2.bits (), test_set(b1).bits ()); rw_info (!i, 0, __LINE__, "std::bitset<%d>::operator>>=(size_t)", N); const test_set ts3 = test_set(ts1) >>= i % M; std::bitset b2 = std::bitset(std::string (ts1.bits ())); // 23.3.5.2, p9 b2 >>= i % M; rw_assert (test_set(b2) == ts3, 0, __LINE__, "bitset<%d>::operator>>=(%lu): %s >> %lu == %s, got %s", N, i % M, ts1.bits (), i % M, ts3.bits (), test_set(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 void test_other (const std::bitset*) { for (std::size_t i = 0; i != NLOOPS; ++i) { // 23.3.5.2, p23 test_set ts1; ts1.random (); test_set ts2 = ~ts1; std::bitset b1 = std::bitset(std::string (ts1.bits ())); std::bitset b2 = ~b1; rw_assert (ts2 == test_set(b2), 0, __LINE__, "bitset<%d>::operator~(): ~%s == %s, got %s", N, ts1.bits (), ts2.bits (), test_set(b2).bits ()); // 23.3.5.2, p25 b2.flip (); rw_assert (ts1 == test_set(b2), 0, __LINE__, "bitset<%d>::flip (): ~%s == %s, got %s", N, ts1.bits (), ts2.bits (), test_set(b2).bits ()); // 23.3.5.2, p27 for (std::size_t _j = 0; _j != N; ++_j) b2.flip (_j); rw_assert (ts2 == test_set(b2), 0, __LINE__, "bitset<%d>::flip () == %s, got %s", N, ts2.bits (), test_set(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(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(b2).bits () : ""); // 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(b2).bits () : ""); // 23.3.5.3, p42 rw_assert (b2.count() && b2.any() || !b2.count() && !b2.any(), 0, __LINE__, "bitset<%d>::any () [%s]", N, test_set(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(b2).bits ()); for (std::size_t k = 0; k != N; ++k) { test_set ts3 = test_set(ts1) <<= k; std::bitset b3 = b1 << k; rw_assert (test_set(b3) == ts3, 0, __LINE__, "bitset<%lu>::operator<<(%lu)", N, k); ts3 = test_set(ts1) >>= k; b3 = b1 >> k; rw_assert (test_set(b3) == ts3, 0, __LINE__, "bitset<%lu>::operator>>(%lu)", N, k); } } } /**************************************************************************/ template void stress_count (const std::bitset*) { rw_info (0, 0, __LINE__, "std::bitset<%lu>::count()", N); for (std::size_t i = 0; i != N; i++) { std::bitset 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 void test_elem_access (const std::bitset*) { 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 ts = test_set().random (); std::bitset b = std::bitset(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(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(b).bits ()); // 23.3.5.2, p??: see lwg issue 11 rw_assert (((const std::bitset&)b) [_j] == ts.test (_j), 0, __LINE__, "bitset<%lu>::operator[](%lu) const: %s", N, _j, test_set(b).bits ()); // exercise std::bitset::reference _TYPENAME std::bitset::reference r = b [_j]; // std::bitset::reference::flip() r.flip (); rw_assert (r == !ts.test (_j), 0, __LINE__, "bitset<%lu>::reference::flip()", N); // std::bitset::reference::operator~() bool toggled = ~r; rw_assert (toggled == ts.test (_j), 0, __LINE__, "bitset<%lu>::reference::operator~()", N); // std::bitset::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: UserTraits { }; } // 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 const char* traits_name (const std::char_traits*) { static char name [64]; std::sprintf (name, "std::char_traits<%s>", type_name (charT ())); return name; } const char* traits_name (const UserTraits*) { return "UserTraits"; } template struct MyAlloc: std::allocator { }; template const char* alloc_name (const std::allocator&) { static char name [64]; std::sprintf (name, "std::allocator<%s>", type_name (charT ())); return name; } template const char* alloc_name (const MyAlloc&) { static char name [64]; std::sprintf (name, "MyAlloc<%s>", type_name (charT ())); return name; } template 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 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::to_string() member function template, // explicitly specifying all three template arguments, // and 2, 1, or 0 of the two default function arguments template std::basic_string bitset_to_string_3 (const std::bitset &bs, int nfargs, charT zero, charT one, std::basic_string*) { // invoke to_string with the number of function arguments specified switch (nfargs) { case 1: return bs.template to_string(zero); case 0: return bs.template to_string(); } return bs.template to_string(zero, one); } template std::basic_string bitset_to_string_3 (const std::bitset &bs, int nfargs, UserChar zero, UserChar one, std::basic_string*) { // 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(zero, dig [1]); case 0: return bs.template to_string(dig [0], dig [1]); } return bs.template to_string(zero, one); } // call the bitset::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::basic_string > bitset_to_string_2 (const std::bitset &bs, int nfargs, charT zero, charT one, std::basic_string >*) { // invoke to_string with the number of function arguments specified switch (nfargs) { case 1: return bs.template to_string(zero); case 0: return bs.template to_string(); } return bs.template to_string(zero, one); } template std::basic_string > bitset_to_string_2 (const std::bitset &bs, int nfargs, UserChar zero, UserChar one, std::basic_string >*) { 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(zero, dig [1]); case 0: return bs.template to_string(dig [0], dig [1]); } return bs.template to_string(zero, one); } // call the bitset::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::basic_string, std::allocator > bitset_to_string_1 (const std::bitset &bs, int nfargs, charT zero, charT one, std::basic_string, std::allocator >*) { // invoke to_string with the number of function arguments specified switch (nfargs) { case 1: return bs.template to_string(zero); case 0: return bs.template to_string(); } return bs.template to_string(zero, one); } template std::basic_string, std::allocator > bitset_to_string_1 (const std::bitset &bs, int nfargs, UserChar zero, UserChar one, std::basic_string, std::allocator >*) { // 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(zero, dig [1]); case 0: return bs.template to_string(dig [0], dig [1]); } return bs.template to_string(zero, one); } #endif // _RWSTD_NO_MEMBER_TEMPLATES // call the bitset::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::basic_string, std::allocator > bitset_to_string_0 (const std::bitset &bs, int nfargs, char zero, char one, std::basic_string, std::allocator >*) { // 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 std::string narrow_string (const std::basic_string &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 void test_to_string (std::bitset*, 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 ts; ts.random (); const std::bitset 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, and allocator typedef std::basic_string 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 rw_info (0, 0, __LINE__, "std::bitset<%lu>::to_string<%s, %s >()", N, cname, tname); typedef std::allocator CharTAlloc; typedef std::basic_string 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 CharTraits; typedef std::basic_string 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 void test_to_string (const std::bitset*) { test_to_string ((std::bitset*)0, (char*)0, (std::char_traits*)0, (std::allocator*)0, false); #ifndef _RWSTD_NO_WCHAR_T test_to_string ((std::bitset*)0, (wchar_t*)0, (std::char_traits*)0, (std::allocator*)0, true); #endif // _RWSTD_NO_WCHAR_T test_to_string ((std::bitset*)0, (UserChar*)0, (UserTraits*)0, (std::allocator*)0, true); } /**************************************************************************/ template void run_test (const std::bitset*) { test_ctors ((std::bitset*)0); stress_ctors ((std::bitset*)0); test_elem_access ((std::bitset*)0); test_operators ((std::bitset*)0); test_other ((std::bitset*)0); stress_count ((std::bitset*)0); test_to_string ((std::bitset*)0); } /**************************************************************************/ static int run_test (int, char**) { test_synopsis ((std::bitset<0>*)0); #define DO_TEST(N) run_test ((std::bitset*)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 */); }