user-defined types and basic_string

Benjamin Kosnik bkoz@redhat.com
Fri Aug 23 10:31:00 GMT 2002


Here's an example of how to do a portable, standards-conformant string
class with underlying type of unsigned short. This also works for
things like unsigned char. Comments welcome.

As Matt pointed out, doing the locale work is a bit tricky. I intend
to do that as well, but thought I'd post this first.

-benjamin

// 2002-08-22  Benjamin Kosnik  <bkoz@redhat.com>

#include <string>
#include <locale>

// Assumes pass-by-value is ok, --> simple type, probably builtin.
// If this is not the case, don't have operator and have specific operators.
struct character
{
  typedef unsigned short 	value_type;
  value_type			value;
  
  explicit character(): value(value_type()) { }
  character(const value_type ch): value(ch) { }
  operator value_type() const { return this->value; }
}; 

// Provide std::char_traits specialization.
namespace std
{
  template<>
    struct char_traits<character>
    {
      typedef character 	 char_type;

      // NB: this type should be bigger than char_type, so as to
      // properly hold EOF values in addition to the full range of
      // char_type values.
      typedef unsigned long  	int_type;

      typedef streampos 	pos_type;
      typedef streamoff 	off_type;
      typedef mbstate_t 	state_type;
      
      static void 
      assign(char_type& __c1, const char_type& __c2)
      { __c1 = __c2; }

      static bool 
      eq(const char_type& __c1, const char_type& __c2)
      { return __c1 == __c2; }

      static bool 
      lt(const char_type& __c1, const char_type& __c2)
      { return __c1 < __c2; }

      static int 
      compare(const char_type* __s1, const char_type* __s2, size_t __n)
      { 
	for (size_t __i = 0; __i < __n; ++__i)
	  if (!eq(__s1[__i], __s2[__i]))
	    return lt(__s1[__i], __s2[__i]) ? -1 : 1;
	return 0; 
      }

      static size_t
      length(const char_type* __s)
      { 
	const char_type* __p = __s; 
	while (*__p) ++__p; 
	return (__p - __s); 
      }

      static const char_type* 
      find(const char_type* __s, size_t __n, const char_type& __a)
      { 
	for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p)
	  if (*__p == __a) return __p;
	return 0;
      }

      static char_type* 
      move(char_type* __s1, const char_type* __s2, size_t __n)
      { return (char_type*) memmove(__s1, __s2, __n * sizeof(char_type)); }

      static char_type* 
      copy(char_type* __s1, const char_type* __s2, size_t __n)
      { return (char_type*) memcpy(__s1, __s2, __n * sizeof(char_type)); }

      static char_type* 
      assign(char_type* __s, size_t __n, char_type __a)
      { 
	for (char_type* __p = __s; __p < __s + __n; ++__p) 
	  assign(*__p, __a);
        return __s; 
      }

      static char_type 
      to_char_type(const int_type& __c)
      { return char_type(__c); }

      static int_type 
      to_int_type(const char_type& __c) { return int_type(__c); }

      static bool 
      eq_int_type(const int_type& __c1, const int_type& __c2)
      { return __c1 == __c2; }

      static int_type 
      eof() { return static_cast<int_type>(-1); }

      static int_type 
      not_eof(const int_type& __c)
      { return eq_int_type(__c, eof()) ? int_type(0) : __c; }
    };
};



int main()
{
  using namespace std;
  typedef character 			char_type;
  typedef character::value_type		value_type;
  typedef char_traits<char_type> 	traits_type;

  bool test = true;

  // 1 char_type <-> value_type conversions
  value_type uc1 = 'c';
  value_type uc2 = 'd';
  char_type c1(uc1);
  char_type c2(uc2);
  test = c1 == uc1;

  // 2 char_traits
  test = traits_type::eq(c1, c2);
  
  // 3 basic_string<char_type>
  typedef basic_string<char_type>	string_type;
  string_type str;
  str += char_type('b');
  str += char_type('o');
  str += char_type('r');
  str += char_type('a');
  str += char_type('c');
  str += char_type('a');
  str += char_type('y');
  string_type::size_type len = str.size();
  const char_type* arr = str.c_str();

  return 0;
}



More information about the Libstdc++ mailing list