This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: user-defined types and basic_string


Benjamin Kosnik wrote:

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.

You'd need to get rid of the character ctors to make it conforming and
portable (the type must be a POD), but other than that it looks pretty
close to our charT that we test string and iostreams with (see below) :)

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.

You must have a lot of time on your hands ;-) Are you really willing
to rewrite all facets as an exercise? I think the only feasible approach
would be to either add a traits template parameter to them or diligently
use char_traits<char_type> in all facets and hope that the user
specializes it rather than creating their own (unrelated) class.

Martin



struct C // user-defined character type (must be POD)
{
#ifndef _RWSTD_NO_LONG_DOUBLE
long double f; // exercise correct alignment
#else
double f;
#endif // _RWSTD_NO_LONG_DOUBLE

unsigned char c; // underlying character representation

// definition of a POD-struct (9, p4):
// A POD-struct is an aggregate class that has no non-static data
// members of type pointer to member, non-POD-struct, non-POD-union
// (or array of such types) or reference, and has no user-defined
// copy assign-ment operator and no user-defined destructor.

// definition of an aggregate (8.5.1, p1):
// An aggregate is an array or a class (clause 9) with no user-declared
// constructors (12.1), no private or protected non-static data members
// (clause 11), no base classes (clause 10), and no virtual functions
// (10.3).
};


struct I // user-defined int type (must be POD)
{
int i; // underlying int representation

void* dummy; // waste space
};


struct C_traits // user-defined character traits
{
typedef C char_type;
typedef I int_type;

// avoid any dependency on the library
typedef int off_type; // std::streamoff
typedef int state_type; // std::mbstate_t
typedef std::fpos<state_type> pos_type; // std::fpos<state_type>

// accesses to the char_type::f member may trigger a SIGBUS
// on some architectures (e.g., PA or SPARC) if the member
// isn't appropriately aligned
static void assign (char_type& c1, const char_type& c2) {
c1.f = c2.f;
c1.c = c2.c;
}

static bool eq (const char_type& c1, const char_type& c2) {
return c1.f == c2.f && c1.c == c2.c;
}

static bool lt (const char_type& c1, const char_type& c2) {
return c1.f < c2.f || c1.f == c2.f && c1.c < c2.c;
}

static int compare (const char_type* s1, const char_type* s2, unsigned n) {
unsigned i = 0;
while (i < n) {
if (!eq (s1[i], s2[i])) {
return lt (s1[i], s2[i]) ? -1 : 1;
}
++i;
}
return 0;
}

static unsigned length (const char_type *s) {
unsigned len = 0;
while (!eq (*s++, char_type ()))
++len;
return len;
}

static const char_type*
find (const char_type* s, unsigned n, const char_type& c) {
while (n-- > 0 && !eq (*s, c) )
++s;
return eq (*s, c) ? s : 0;
}

static char_type* move (char_type* s1, const char_type* s2, unsigned n) {
if (s1 < s2)
copy (s1, s2, n);
else if (s1 > s2) {
s1 += n;
s2 += n;
for (unsigned i = 0; i < n; ++i)
assign (*--s1, *--s2);
}
return s1;
}

static char_type* copy (char_type *dst, const char_type *src, unsigned n) {
for (; n--; *dst++ = *src++);
return dst;
}

static char_type* assign (char_type* s, unsigned n, char_type c) {
char_type* tmp = s;
while (n-- > 0)
assign (*tmp++, c);
return s;
}

static int_type not_eof (const int_type& i) {
I tmp = { -1 == i.i ? 0 : i.i, 0};
return tmp;
}

static char_type to_char_type (const int_type& i) {
C tmp = { 0.0, i.i };
return tmp;
}

static int_type to_int_type (const char_type& c) {
I tmp = { c.c, 0 };
return tmp;
}

static bool eq_int_type (const int_type& i1, const int_type& i2) {
return i1.i == i2.i;
}

static int_type eof () {
I tmp = { -1, 0 };
return tmp;
}
};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]