You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/05/26 00:12:22 UTC

svn commit: r409484 - in /incubator/stdcxx/trunk/tests: include/21.strings.h src/21.strings.cpp

Author: sebor
Date: Thu May 25 15:12:21 2006
New Revision: 409484

URL: http://svn.apache.org/viewvc?rev=409484&view=rev
Log:
2006-05-25  Martin Sebor  <se...@roguewave.com>

	* 21.strings.h (FuncId): Added members, increased to 6 bits.
	(bit_member): New enumerator designating member functions.
	(OverloadId): Added enumerator for operator+, operator==,
	operator!=, and all relational operators.
	* 21.strings.cpp (_rw_func_names): Added function names.
	(_rw_class_name): New helper function to compute the name
	of the basic_string class (string, wstring, or basic_string).
	(_rw_sigcat): Used mnemonics instead of real function names
	for name of options controlling operators (such as operator+).
	Handled non-members correctly.
	(_rw_uses_alloc): New helper to help determine whether a ctor
	overload takes an allocator argument.
	(_rw_setvars): Formatted ctors and non-members correctly.
	Added formatting handlers for missing ctor overloads.
	Added formatting handlers for non-member functions.

Modified:
    incubator/stdcxx/trunk/tests/include/21.strings.h
    incubator/stdcxx/trunk/tests/src/21.strings.cpp

Modified: incubator/stdcxx/trunk/tests/include/21.strings.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/21.strings.h?rev=409484&r1=409483&r2=409484&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/include/21.strings.h (original)
+++ incubator/stdcxx/trunk/tests/include/21.strings.h Thu May 25 15:12:21 2006
@@ -37,16 +37,16 @@
     // identifiers for the charT template argument
     enum CharId { Char, WChar, UChar };
 
-    // identifiers for  the Traits template argument
+    // identifiers for the Traits template argument
     enum TraitsId { DefaultTraits, UserTraits };
 
-    // identifiers for  the Allocator template argument
+    // identifiers for the Allocator template argument
     enum AllocId { DefaultAlloc, UserAlloc };
 
     // identifies a set of overloaded member or non-member
     // string functions
     enum FuncId {
-        // 5 bits, 32 functions max
+        // 6 bits, 64 functions max
         /*  0 */ fid_append,
         /*  1 */ fid_assign,
         /*  2 */ fid_erase,
@@ -70,8 +70,15 @@
         /* 18 */ fid_op_set,
         /* 19 */ fid_swap,
         /* 20 */ fid_push_back,
-        /* -- */ fid_bits = 5,
-        /* -- */ fid_mask = 31
+        /* 21 */ fid_op_plus,
+        /* 22 */ fid_op_equal,
+        /* 23 */ fid_op_not_equal,
+        /* 24 */ fid_op_less,
+        /* 25 */ fid_op_less_equal,
+        /* 26 */ fid_op_greater,
+        /* 27 */ fid_op_greater_equal,
+        /* -- */ fid_bits = 6,
+        /* -- */ fid_mask = 63
     };
 
     // identifies the type of a function argument, including
@@ -95,8 +102,16 @@
         /* -- */ arg_mask = 15
     };
 
+    enum {
+        // bit designating a member function
+        bit_member = 1 << fid_bits + 6 * arg_bits
+    };
+
+// FCAT() concatenates prefix, underscrore, and suffix
 #define _FCAT(a, b)             a ## b
 #define FCAT(a, b)              _FCAT (a ## _, b)
+
+// FID_N() constructs the name for an overload of a string function
 #define FID_0(f)                FCAT (f, void)
 #define FID_1(f, a)             FCAT (f, a)
 #define FID_2(f, a, b)          FID_1 (FCAT (f, a), b)
@@ -104,8 +119,10 @@
 #define FID_4(f, a, b, c, d)    FID_3 (FCAT (f, a), b, c, d)
 #define FID_5(f, a, b, c, d, e) FID_4 (FCAT (f, a), b, c, d, e)
 
-#define ARG(a, N)   ((arg_ ## a << (N << 2)) << 5)
+// ARG() creates a bitmap of an argument type at the given position
+#define ARG(a, N)   ((arg_ ## a << (N * arg_bits)) << fid_bits)
 
+// SIG_N() creates an argument bitmap for the given function signature
 #define SIG_0(f)                   fid_ ## f
 #define SIG_1(f, a)                SIG_0 (f) | ARG (a, 0)
 #define SIG_2(f, a, b)             SIG_1 (f, a) | ARG (b, 1)
@@ -118,17 +135,17 @@
 // where the first argument encodes the constness of the member
 // function (or the lack thereof)
 #define MEMBER_0(f, self) \
-        FID_0 (f) = SIG_1 (f, self)
+        FID_0 (f) = SIG_1 (f, self) | bit_member
 #define MEMBER_1(f, self, a) \
-        FID_1 (f, a) = SIG_2 (f, self, a)
+        FID_1 (f, a) = SIG_2 (f, self, a) | bit_member
 #define MEMBER_2(f, self, a, b) \
-        FID_2 (f, a, b) = SIG_3 (f, self, a, b)
+        FID_2 (f, a, b) = SIG_3 (f, self, a, b) | bit_member
 #define MEMBER_3(f, self, a, b, c) \
-        FID_3 (f, a, b, c) = SIG_4 (f, self, a, b, c)
+        FID_3 (f, a, b, c) = SIG_4 (f, self, a, b, c) | bit_member
 #define MEMBER_4(f, self, a, b, c, d) \
-        FID_4 (f, a, b, c, d) = SIG_5 (f, self, a, b, c, d)
+        FID_4 (f, a, b, c, d) = SIG_5 (f, self, a, b, c, d) | bit_member
 #define MEMBER_5(f, self, a, b, c, d, e) \
-        FID_5 (f, a, b, c, d, e) = SIG_6 (f, self, a, b, c, d, e)
+        FID_5 (f, a, b, c, d, e) = SIG_6 (f, self, a, b, c, d, e) | bit_member
 
 // convenience macro to define non-member function overload id's
 #define NON_MEMBER_0(f) \
@@ -145,6 +162,9 @@
         FID_5 (f, a, b, c, d, e) = SIG_5 (f, a, b, c, d, e)
 
     // unique identifiers for all overloads of each member function
+    //     6 bits for FuncId
+    // 6 * 4 bits for ArgId (at most 6 arguments including this)
+    //     1 bit for membership
     enum OverloadId {
         //////////////////////////////////////////////////////////////
         // append (const_pointer)
@@ -420,7 +440,67 @@
 
         //////////////////////////////////////////////////////////////
         // push_back (value_type)
-        MEMBER_1 (push_back, str, val)
+        MEMBER_1 (push_back, str, val),
+
+        //////////////////////////////////////////////////////////////
+        // operator+ (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_plus, cptr, cstr),
+        // operator+ (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_plus, cstr, cstr),
+        // operator+ (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_plus, cstr, cptr),
+        // operator+ (const basic_string&, value_type)
+        NON_MEMBER_2 (op_plus, cstr, val),
+        // operator+ (value_type, const basic_string&)
+        NON_MEMBER_2 (op_plus, val, cstr),
+
+        //////////////////////////////////////////////////////////////
+        // operator== (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_equal, cptr, cstr),
+        // operator== (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_equal, cstr, cstr),
+        // operator== (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_equal, cstr, cptr),
+
+        //////////////////////////////////////////////////////////////
+        // operator!= (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_not_equal, cptr, cstr),
+        // operator!= (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_not_equal, cstr, cstr),
+        // operator!= (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_not_equal, cstr, cptr),
+
+        //////////////////////////////////////////////////////////////
+        // operator< (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_less, cptr, cstr),
+        // operator< (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_less, cstr, cstr),
+        // operator< (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_less, cstr, cptr),
+
+        //////////////////////////////////////////////////////////////
+        // operator<= (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_less_equal, cptr, cstr),
+        // operator<= (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_less_equal, cstr, cstr),
+        // operator<= (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_less_equal, cstr, cptr),
+
+        //////////////////////////////////////////////////////////////
+        // operator> (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_greater, cptr, cstr),
+        // operator> (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_greater, cstr, cstr),
+        // operator> (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_greater, cstr, cptr),
+
+        //////////////////////////////////////////////////////////////
+        // operator>= (const_pointer, const basic_string&)
+        NON_MEMBER_2 (op_greater_equal, cptr, cstr),
+        // operator>= (const basic_string&, const basic_string&)
+        NON_MEMBER_2 (op_greater_equal, cstr, cstr),
+        // operator>= (const basic_string&, const_pointer)
+        NON_MEMBER_2 (op_greater_equal, cstr, cptr)
     };
 
 // clean up helper macros used above

Modified: incubator/stdcxx/trunk/tests/src/21.strings.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/21.strings.cpp?rev=409484&r1=409483&r2=409484&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/21.strings.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/21.strings.cpp Thu May 25 15:12:21 2006
@@ -71,7 +71,9 @@
     "append", "assign", "erase", "insert", "replace", "operator+=", "find", 
     "rfind", "find_first_of", "find_last_of", "find_first_not_of", 
     "find_last_not_of", "compare", "substr", "operator[]", "at", "copy",
-    "constructor", "operator=", "swap", "push_back"
+    0 /* special handling for the ctor */, "operator=", "swap", "push_back",
+    "operator+", "operator==", "operator!=", "operator<", "operator<=",
+    "operator>", "operator>="
 };
 
 /**************************************************************************/
@@ -148,48 +150,140 @@
                when);
 }
 
+/**************************************************************************/
+
+static const char*
+_rw_class_name (const StringFunc &func)
+{
+    if (   StringIds::DefaultTraits == func.traits_id_
+        && StringIds::DefaultAlloc == func.alloc_id_) {
+
+        if (StringIds::Char == func.char_id_)
+            return "string";
+
+        if (StringIds::WChar == func.char_id_)
+            return "wstring";
+    }
+
+    return "basic_string";
+}
 
 /**************************************************************************/
 
 // appends the signature of the function specified by which
-// to the provided buffer; when brief is true, appends the
-// mnemonic representing the signature, including the name
-// of the function, instead
+// to the provided buffer; when the second argument is null,
+// appends the mnemonic representing the signature, including
+// the name of the function, as specified by the third argument
 static void
 _rw_sigcat (char **pbuf, size_t *pbufsize,
-            StringIds::OverloadId which,
-            bool                  brief = false)
+            const StringFunc      *func,
+            StringIds::OverloadId  which = StringIds::OverloadId ())
 {
     // for convenience
     typedef StringIds Ids;
 
+    if (func)
+        which = func->which_;
+
+    // determine whether the function is a member function
+    const bool is_member = Ids::bit_member & which;
+
     // get the bitmap describing the function's argument types
-    int argmap = which >> Ids::fid_bits;
+    int argmap = (which & ~Ids::bit_member) >> Ids::fid_bits;
 
     // determine whether the function is a const member function
-    const bool is_const = Ids::arg_cstr == (argmap & Ids::arg_mask);
+    bool is_const_member =
+        is_member && Ids::arg_cstr == (argmap & Ids::arg_mask);
 
-    // determine the string function name (for brief output)
-    const size_t funcinx = which & StringIds::fid_mask;
-    const size_t nfuncs =  sizeof _rw_func_names / sizeof *_rw_func_names;
+    // remove the *this argument if the function is a member
+    if (is_member)
+        argmap >>= Ids::arg_bits;
+
+    const char* funcname = 0;
+
+    if (0 == func) {
+        const Ids::FuncId fid = Ids::FuncId (which & StringIds::fid_mask);
+
+        switch (fid) {
+            // translate names with funky characters to mnemonics
+        case Ids::fid_ctor:          funcname = "ctor"; break;
+        case Ids::fid_op_plus_eq:    funcname = "op_plus_eq"; break;
+        case Ids::fid_op_index:      funcname = "op_index"; break;
+        case Ids::fid_op_set:        funcname = "op_assign"; break;
+        case Ids::fid_op_plus:       funcname = "op_plus"; break;
+        case Ids::fid_op_equal:      funcname = "op_equal"; break;
+        case Ids::fid_op_not_equal:  funcname = "op_not_equal"; break;
+        case Ids::fid_op_less:       funcname = "op_less"; break;
+        case Ids::fid_op_less_equal: funcname = "op_less_equal"; break;
+        case Ids::fid_op_greater:    funcname = "op_greater"; break;
+        case Ids::fid_op_greater_equal: funcname = "op_greater_equal"; break;
+
+        case Ids::fid_compare:
+        case Ids::fid_copy:
+        case Ids::fid_find:
+        case Ids::fid_find_first_not_of:
+        case Ids::fid_find_first_of:
+        case Ids::fid_find_last_not_of:
+        case Ids::fid_find_last_of:
+        case Ids::fid_rfind:
+        case Ids::fid_substr:
+            // prevent appending the "_const" bit to the mnemonics
+            // of member functions not overloaded on const
+            is_const_member = false;
+
+            // fall through
+
+        default: {
+            // determine the string function name (for brief output)
+            const size_t nfuncs =
+                sizeof _rw_func_names / sizeof *_rw_func_names;
 
-    RW_ASSERT (funcinx < nfuncs);
+            RW_ASSERT (size_t (fid) < nfuncs);
 
-    const char* const funcname = _rw_func_names [funcinx];
+            funcname = _rw_func_names [fid];
+            RW_ASSERT (0 != funcname);
+            break;
+        }
+        }
+    }
 
     rw_asnprintf (pbuf, pbufsize, "%{+}%{?}%s%{?}_const%{;}%{:}(%{;}",
-                  brief, funcname, is_const);
+                  0 == func, funcname, is_const_member);
 
     // iterate through the map of argument types one field at a time
     // determining and formatting the type of each argument until
     // void is reached
-    for (size_t argno = 0; argmap >>= Ids::arg_bits; ++argno) {
+    for (size_t argno = 0; argmap; ++argno, argmap >>= Ids::arg_bits) {
+
+        const char* pfx = "";
+        const char* sfx = "";
 
         const int argtype = argmap & Ids::arg_mask;
 
         const char* tname = 0;
 
-        if (brief) {
+        if (func) {
+            switch (argtype) {
+            case Ids::arg_size:  tname = "size_type"; break;
+            case Ids::arg_val:   tname = "value_type"; break;
+            case Ids::arg_ptr:   tname = "pointer"; break;
+            case Ids::arg_cptr:  tname = "const_pointer"; break;
+            case Ids::arg_ref:   tname = "reference"; break;
+            case Ids::arg_cref:  tname = "const_reference"; break;
+            case Ids::arg_iter:  tname = "iterator"; break;
+            case Ids::arg_citer: tname = "const_iterator"; break;
+            case Ids::arg_range: tname = "InputIterator, InputIterator"; break;
+            case Ids::arg_alloc: tname = "const allocator_type&"; break;
+            case Ids::arg_cstr:
+                pfx   = "const ";
+                // fall through
+            case Ids::arg_str:
+                tname = _rw_class_name (*func);
+                sfx   = "&";
+                break;
+            }
+        }
+        else {
             switch (argtype) {
             case Ids::arg_size:  tname = "size"; break;
             case Ids::arg_val:   tname = "val"; break;
@@ -200,39 +294,53 @@
             case Ids::arg_iter:  tname = "iter"; break;
             case Ids::arg_citer: tname = "citer"; break;
             case Ids::arg_range: tname = "range"; break;
+            case Ids::arg_alloc: tname = "alloc"; break;
             case Ids::arg_str:   tname = "str"; break;
             case Ids::arg_cstr:  tname = "cstr"; break;
-            case Ids::arg_alloc: tname = "alloc"; break;
             }
         }
+
+        RW_ASSERT (0 != tname);
+
+        if (   0 == func || is_member
+            || Ids::arg_str != argtype && Ids::arg_cstr != argtype) {
+            // append the name or mnemonic of the argument type
+            rw_asnprintf (pbuf, pbufsize, "%{+}%{?}_%{:}%{?}, %{;}%{;}%s%s%s",
+                          0 == func, 0 < argno, pfx, tname, sfx);
+        }
         else {
-            switch (argtype) {
-            case Ids::arg_size:  tname = "size_type"; break;
-            case Ids::arg_val:   tname = "value_type"; break;
-            case Ids::arg_ptr:   tname = "pointer"; break;
-            case Ids::arg_cptr:  tname = "const_pointer"; break;
-            case Ids::arg_ref:   tname = "reference"; break;
-            case Ids::arg_cref:  tname = "const_reference"; break;
-            case Ids::arg_iter:  tname = "iterator"; break;
-            case Ids::arg_citer: tname = "const_iterator"; break;
-            case Ids::arg_range: tname = "InputIterator, InputIterator"; break;
-            case Ids::arg_str:   tname = "basic_string&"; break;
-            case Ids::arg_cstr:  tname = "const basic_string&"; break;
-            case Ids::arg_alloc: tname = "const allocator_type&"; break;
-            }
+            // in non-member functions use ${CLASS} to format
+            // the basic_string argument in order to expand
+            // its template argument list
+            rw_asnprintf (pbuf, pbufsize,
+                          "%{+}%{?}, %{;}%{?}const %{$CLASS}&%{;}",
+                          0 < argno, Ids::arg_cstr == argtype);
+            
         }
+    }
 
-        RW_ASSERT (0 != tname);
+    if (func)
+        rw_asnprintf (pbuf, pbufsize, "%{+})%{?} const%{;}", is_const_member);
+}
+
+/**************************************************************************/
+
+static bool
+_rw_uses_alloc (StringIds::OverloadId which)
+{
+    // get the bitmap describing the function's argument types
+    int argmap = (which & ~StringIds::bit_member) >> StringIds::fid_bits;
 
-        // append the name of the argument type
-        rw_asnprintf (pbuf, pbufsize, "%{+}%{?}_%{:}%{?}, %{;}%{;}%s",
-                      brief, 0 < argno, tname);
+    for (; argmap; argmap >>= StringIds::arg_bits) {
+        if ((argmap & StringIds::arg_alloc) == StringIds::arg_alloc)
+            return true;
     }
 
-    if (!brief)
-        rw_asnprintf (pbuf, pbufsize, "%{+})%{?} const%{;}", is_const);
+    return false;
 }
 
+/**************************************************************************/
+
 // sets the {CLASS}, {FUNC}, {FUNCSIG}, and optionally {FUNCALL}
 // environment variables as follows:
 // CLASS:   the name of basic_string specialization
@@ -249,6 +357,8 @@
     char*  buf     = 0;
     size_t bufsize = 0;
 
+    const char* const class_name = _rw_class_name (func);
+
     if (0 == pcase) {
         // set the {charT}, {Traits}, and {Allocator} environment
         // variables to the name of the character type and the
@@ -297,21 +407,29 @@
 
         RW_ASSERT (funcinx < nfuncs);
 
-        const char* const funcname = _rw_func_names [funcinx];
-
         free (buf);
         buf     = 0;
         bufsize = 0;
 
-        // set the {FUNC} variable to the unqualified name
-        // of the string function
-        rw_asnprintf (&buf, &bufsize, "%s", funcname);
+        // get the undecorated function name; ctors are treated
+        // specially so that we can have string, wstring, or
+        // basic_string, depending on the template arguments
+        const char* const funcname = _rw_func_names [funcinx] ?
+            _rw_func_names [funcinx] : class_name;
+
+        // determine whether the function is a member function
+        const bool is_member = func.which_ & StringIds::bit_member;
+
+        // set the {FUNC} variable to the unqualified/undecorated
+        // name of the string function (member or otherwise)
+        rw_asnprintf (&buf, &bufsize, "%{?}std::%{;}%s",
+                      !is_member, funcname);
 
         rw_putenv ("FUNC=");
         rw_fprintf (0, "%{$FUNC:=*}", buf);
 
         // append the function signature
-        _rw_sigcat (&buf, &bufsize, func.which_);
+        _rw_sigcat (&buf, &bufsize, &func);
 
         rw_putenv ("FUNCSIG=");
         rw_fprintf (0, "%{$FUNCSIG:=*}", buf);
@@ -342,15 +460,38 @@
     else
         arg = 0;
 
-    // append the ctor argument(s) and the string function name
-    rw_asnprintf (&buf, &bufsize,
-                  "%{$CLASS} (%{?}%{#*s}%{;}).%{$FUNC} ",
-                  str != 0, int (str_len), str);
+    // determine whether the function is a member function
+    const bool is_member = func.which_ & StringIds::bit_member;
+
+    // determine whether the function is a ctor
+    bool is_ctor = StringIds::fid_ctor == (func.which_ & StringIds::fid_mask);
+
+    if (is_ctor) {
+        // for ctors append just the class name here
+        // the class name will inserted below during argument
+        // formatting
+        rw_asnprintf (&buf, &bufsize, "%{$CLASS}::%s", class_name);
+    }
+    else if (is_member) {
+        // for other members append the ctor argument(s) followed
+        // by the string member function name
+        rw_asnprintf (&buf, &bufsize,
+                      "%{$CLASS} (%{?}%{#*s}%{;}).%{$FUNC} ",
+                      str != 0, int (str_len), str);
+    }
+    else {
+        // for non-members append just the function name here
+        // the class name will inserted below during argument
+        // formatting
+        rw_asnprintf (&buf, &bufsize, "%{$FUNC} ");
+    }
 
     // compute the end offsets for convenience
     const size_t range1_end = pcase->off + pcase->size;
     const size_t range2_end = pcase->off2 + pcase->size2;
 
+    const bool use_alloc = _rw_uses_alloc (func.which_);
+
     // format and append string function arguments abbreviating complex
     // expressions as much as possible to make them easy to understand
     switch (func.which_) {
@@ -364,12 +505,14 @@
     case StringIds::find_first_not_of_cptr:
     case StringIds::find_last_not_of_cptr:
     case StringIds::compare_cptr:
-    case StringIds::ctor_cptr:
     case StringIds::op_set_cptr:
+    case StringIds::ctor_cptr:
+    case StringIds::ctor_cptr_alloc:
         // format self-referential ptr argument without size as c_str()
         rw_asnprintf (&buf, &bufsize,
-                      "%{+}(%{?}c_str()%{:}%{#*s}%{;})",
-                      self, int (arg_len), arg);
+                      "%{+}(%{?}c_str()%{:}%{#*s}%{;}"
+                      "%{?}, const allocator_type&%{;})",
+                      self, int (arg_len), arg, use_alloc);
         break;
 
     case StringIds::append_cstr:
@@ -383,22 +526,26 @@
     case StringIds::find_last_not_of_cstr:
     case StringIds::compare_cstr:
     case StringIds::ctor_cstr:
+    case StringIds::ctor_cstr_alloc:
     case StringIds::op_set_cstr:
     case StringIds::swap_str:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize,
-                      "%{+}(%{?}*this%{:}string(%{#*s})%{;})",
-                      self, int (arg_len), arg);
+                      "%{+}(%{?}*this%{:}%s(%{#*s})%{;}"
+                      "%{?}, const allocator_type&%{;})",
+                      self, class_name, int (arg_len), arg, use_alloc);
         break;
 
     case StringIds::append_cptr_size:
     case StringIds::assign_cptr_size:
     case StringIds::copy_ptr_size:
     case StringIds::ctor_cptr_size:
+    case StringIds::ctor_cptr_size_alloc:
         // format self-referential ptr argument with size as data()
         rw_asnprintf (&buf, &bufsize, "%{+}("
-                      "%{?}data()%{:}%{#*s}%{;}, %zu)",
-                      self, int (arg_len), arg, pcase->size);
+                      "%{?}data()%{:}%{#*s}%{;}, %zu"
+                      "%{?}, const allocator_type&%{;})",
+                      self, int (arg_len), arg, pcase->size, use_alloc);
         break;
 
     case StringIds::find_cptr_size:
@@ -420,10 +567,13 @@
     case StringIds::find_first_not_of_cstr_size:
     case StringIds::find_last_not_of_cstr_size:
     case StringIds::ctor_cstr_size:
+    case StringIds::ctor_cstr_size_alloc:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize, "%{+}("
-                      "%{?}*this%{:}string(%{#*s})%{;}, %zu)",
-                      self, int (arg_len), arg, pcase->off);
+                      "%{?}*this%{:}%s(%{#*s})%{;}, %zu"
+                      "%{?}, const allocator_type%{;})",
+                      self, class_name, int (arg_len), arg, pcase->off,
+                      use_alloc);
         break;
 
     case StringIds::find_cptr_size_size:
@@ -450,31 +600,37 @@
     case StringIds::append_cstr_size_size:
     case StringIds::assign_cstr_size_size:
     case StringIds::ctor_cstr_size_size:
+    case StringIds::ctor_cstr_size_size_alloc:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize, "%{+}("
-                      "%{?}*this%{:}string(%{#*s})%{;}, %zu, %zu)",
-                      self, int (arg_len), arg,
-                      pcase->off, pcase->size);
+                      "%{?}*this%{:}%s(%{#*s})%{;}, %zu, %zu"
+                      "%{?}, const allocator_type%{;})",
+                      self, class_name, int (arg_len), arg,
+                      pcase->off, pcase->size, use_alloc);
         break;
 
     case StringIds::append_size_val:
     case StringIds::assign_size_val:
     case StringIds::ctor_size_val:
+    case StringIds::ctor_size_val_alloc:
         rw_asnprintf (&buf, &bufsize,
-                      "%{+}(%zu, %{#c})", pcase->size, pcase->val);
+                      "%{+}(%zu, %{#c}%{?}, const allocator_type&%{;})",
+                      pcase->size, pcase->val, use_alloc);
         break;
 
     case StringIds::append_range:
     case StringIds::assign_range:
     case StringIds::ctor_range:
+    case StringIds::ctor_range_alloc:
         rw_asnprintf (&buf, &bufsize, "%{+}("
                       "%{?}begin()%{:}Iterator(%{#*s})%{;}"
                       "%{?} + %zu%{;}, "
                       "%{?}begin()%{:}Iterator(...)%{;}"
-                      "%{?} + %zu%{;})",
+                      "%{?} + %zu%{;}"
+                      "%{?}, const allocator_type&%{;})",
                       self, int (arg_len), arg,
                       0 != pcase->off, pcase->off,
-                      self, 0 != range1_end, range1_end);
+                      self, 0 != range1_end, range1_end, use_alloc);
         break;
 
     case StringIds::insert_size_cptr:
@@ -487,8 +643,8 @@
     case StringIds::insert_size_cstr:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize,  
-                      "%{+}(%zu, %{?}*this%{:}string(%{#*s})%{;})",
-                      pcase->off, self, int (arg_len), arg);
+                      "%{+}(%zu, %{?}*this%{:}%s(%{#*s})%{;})",
+                      pcase->off, self, class_name, int (arg_len), arg);
         break;
 
     case StringIds::insert_size_cptr_size:
@@ -502,8 +658,8 @@
     case StringIds::insert_size_cstr_size_size:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize, "%{+}("
-                      "%zu, %{?}*this%{:}string(%{#*s})%{;}, %zu, %zu)",
-                      pcase->off, self, int (arg_len), arg,
+                      "%zu, %{?}*this%{:}%s(%{#*s})%{;}, %zu, %zu)",
+                      pcase->off, self, class_name, int (arg_len), arg,
                       pcase->off2, pcase->size2);
         break;
 
@@ -549,8 +705,8 @@
     case StringIds::compare_size_size_cstr:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize, "%{+}("
-                      "%zu, %zu, %{?}*this%{:}string(%{#*s})%{;})",
-                      pcase->off, pcase->size, self, 
+                      "%zu, %zu, %{?}*this%{:}%s(%{#*s})%{;})",
+                      pcase->off, pcase->size, self, class_name,
                       int (arg_len), arg);
         break;
 
@@ -567,9 +723,9 @@
     case StringIds::compare_size_size_cstr_size_size:
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize, "%{+}(%zu, %zu, "
-                      "%{?}*this%{:}string(%{#*s})%{;}, %zu, %zu)",
-                      pcase->off, pcase->size, self,
-                      int (arg_len), arg,
+                      "%{?}*this%{:}%s(%{#*s})%{;}, %zu, %zu)",
+                      pcase->off, pcase->size,
+                      self, class_name, int (arg_len), arg,
                       pcase->off2, pcase->size2);
         break;
 
@@ -593,10 +749,10 @@
         // format self-referential str argument as *this
         rw_asnprintf (&buf, &bufsize, "%{+}(begin()%{?} + %zu%{;}, "
                       "begin()%{?} + %zu%{;}, "
-                      "%{?}*this%{:}string(%{#*s})%{;})",
+                      "%{?}*this%{:}%s(%{#*s})%{;})",
                       0 != pcase->off, pcase->off,
                       0 != range1_end, range1_end,
-                      self, int (arg_len), arg);
+                      self, class_name, int (arg_len), arg);
         break;
 
     case StringIds::replace_iter_iter_cptr_size:
@@ -661,6 +817,11 @@
                       "%{+}()");
         break;
 
+    case StringIds::ctor_alloc:
+        rw_asnprintf (&buf, &bufsize,
+                      "%{+}(const allocator_type&)");
+        break;
+        
     case StringIds::erase_size:
     case StringIds::substr_size:
     case StringIds::op_index_size:
@@ -694,6 +855,60 @@
                       0 != range1_end, range1_end);
         break;
 
+    case StringIds::op_plus_cptr_cstr:
+    case StringIds::op_equal_cptr_cstr:
+    case StringIds::op_not_equal_cptr_cstr:
+    case StringIds::op_less_cptr_cstr:
+    case StringIds::op_less_equal_cptr_cstr:
+    case StringIds::op_greater_cptr_cstr:
+    case StringIds::op_greater_equal_cptr_cstr:
+        // format zero ptr argument without size as arg.c_str()
+        rw_asnprintf (&buf, &bufsize,
+                      "%{+}(%{?}arg2.c_str()%{:}%{#*s}%{;}, "
+                      "%{$CLASS}(%{#*s}))",
+                      0 == str, int (str_len), str, int (arg_len), arg);
+        break;
+
+    case StringIds::op_plus_cstr_cptr:
+    case StringIds::op_equal_cstr_cptr:
+    case StringIds::op_not_equal_cstr_cptr:
+    case StringIds::op_less_cstr_cptr:
+    case StringIds::op_less_equal_cstr_cptr:
+    case StringIds::op_greater_cstr_cptr:
+    case StringIds::op_greater_equal_cstr_cptr:
+        // format zero ptr argument without size as arg.c_str()
+        rw_asnprintf (&buf, &bufsize,
+                      "%{+}(%{$CLASS}(%{#*s}), "
+                      "%{?}arg1.c_str()%{:}%{#*s}%{;})",
+                      int (str_len), str, self, int (arg_len), arg);
+        break;
+
+    case StringIds::op_plus_cstr_cstr:
+    case StringIds::op_equal_cstr_cstr:
+    case StringIds::op_not_equal_cstr_cstr:
+    case StringIds::op_less_cstr_cstr:
+    case StringIds::op_less_equal_cstr_cstr:
+    case StringIds::op_greater_cstr_cstr:
+    case StringIds::op_greater_equal_cstr_cstr:
+        // format zero str argument without size as arg
+        rw_asnprintf (&buf, &bufsize,
+                      "%{+}(%{?}arg2%{:}%{$CLASS}(%{#*s})%{;}, "
+                      "%{?}arg1%{:}%{$CLASS}(%{#*s})%{;})",
+                      0 == str, int (str_len), str, self, int (arg_len), arg);
+        break;
+
+    case StringIds::op_plus_cstr_val:
+        rw_asnprintf (&buf, &bufsize,
+                      "%{+}(%{$CLASS}(%{#*s}), %{#c})",
+                      int (arg_len), arg, pcase->val);
+        break;
+
+    case StringIds::op_plus_val_cstr:
+        rw_asnprintf (&buf, &bufsize,
+                      "%{+}(%{#c}, %{$CLASS}(%{#*s}))",
+                      pcase->val, int (arg_len), arg);
+        break;
+
     default:
         RW_ASSERT (!"test logic error: unknown overload");
     }
@@ -904,6 +1119,9 @@
                     // and the string function being exercised
                     _rw_setvars (func);
 
+                    // determine whether the function is a member function
+                    const bool is_member = StringIds::bit_member & test.which;
+
                     // compute the function overload's 0-based index
                     const size_t siginx = _rw_get_func_inx (test.which);
 
@@ -911,10 +1129,12 @@
                     // have been disabled
                     if (0 == rw_note (0 <= _rw_opt_func [siginx],
                                       _rw_this_file, __LINE__,
-                                      "%{$CLASS}::%{$FUNCSIG} tests disabled"))
+                                      "%{?%{$CLASS}::%{;}%{$FUNCSIG} "
+                                      "tests disabled", is_member))
                         continue;
 
-                    rw_info (0, 0, 0, "%{$CLASS}::%{$FUNCSIG}");
+                    rw_info (0, 0, 0, "%{?}%{$CLASS}::%{;}%{$FUNCSIG}",
+                             is_member);
 
                     const size_t case_count = test.case_count;
 
@@ -975,7 +1195,7 @@
         // for each function append a command line option specification
         // to allow to enable or disable it
         rw_asnprintf (&optbuf, &optbufsize, "%{+}|-");
-        _rw_sigcat (&optbuf, &optbufsize, tests [i].which, true);
+        _rw_sigcat (&optbuf, &optbufsize, 0, tests [i].which);
         rw_asnprintf (&optbuf, &optbufsize, "%{+}~ ");
     }