-------- Original Message --------
Subject: Re: Standard String
Date: Fri, 15 Jul 2005 15:26:00 -0500
From: Andrew Johnson <[email protected]>
Organization: APS, Argonne National Laboratory
To: Marty Kraimer <[email protected]>
CC: Jeff Hill <[email protected]>
References: <[email protected]>
Marty Kraimer wrote:
This is an attempt to see if we can have a standard string implemention.
Jeff said that he wanted it to be an interface class.
Let's look at that idea, without worrying about what it actually looks
like: Assume we have all agreed on a single API for a string class that
I'll call 'StringInterface,' which is a pure interface class.
I can't instantiate an object of type StringInterface since it's a pure
interface class, so in order to create and use a string in my code I
would have to define a pointer to a StringInterface, and call a factory
routine or use some other means to create a concrete object of my chosen
derived class.
StringInterface *pstring = StringFactory(...);
However because I'm using a pointer, I must remember to release that
object (assume for now that just means deleting it) after I've finished
with it in order to avoid leaking memory when my pstring goes out of scope:
delete pstring;
Since I'm a well-educated C++ programmer who understands the RAII idiom
(Resource Acquisition Is Initialization), I know how to solve the
potential memory leak issue: wrap the pointer inside another class which
has a destructor that will delete the string for me.
I could use the standard C++ auto_ptr template to wrap and manage a
StringInterface pointer, but I don't want the destructive assignment
behaviour that it would give me.
I decide to create a new class implementing StringInterface that
contains and manages a StringInterface pointer for me. It will release
the object automatically in its destructor, so no memory leaks. That
class will look something like this:
class SafeString public StringInterface {
private: // Data
StringInterface *psi;
public: // Methods
SafeString(StringInterface *concrete = 0) :
psi(concrete) {}
~SafeString()
{
if (psi) delete psi;
}
SetStringInterface(StringInterface *concrete)
{
if (psi) delete psi;
psi = concrete;
}
// For every method in StringInterface, define
returnType method(...)
{
if (!psi) throw(something...);
psi->method(...);
}
private: // Not implemented:
SafeString(const SafeString& rhs);
SafeString& operator=(const SafeString& rhs);
};
I can now create an instance of a SafeString and know that I can't leak
memory by forgetting to delete the pointer:
SafeString greeting(StringFactory(...));
SafeString isn't a pure interface class since it contains data, but the
only behaviour it actually defines for itself is the ability to manage
that pointer for me. I haven't sacrificed any flexibilty on the part of
the underlying implementation of StringInterface since I forward all the
StringInterface methods to the real implementation, I have just made it
safer to use the StringInterface API.
I'd like to make my SafeString slightly easier to use in a couple of
very common cases:
1. Suppose there's an implementation of StringInterface available
through the StringFactory that takes a C++ 'const char *' literal and
makes it accessible using the StringInterface methods. I decide to add
a constructor to my SafeString class that explicitly creates one of
those kinds of strings when given a 'const char *':
SafeString(const char *pstr) :
psi(StringFactory(..., pstr)) {}
I can now write code like this:
SafeString greeting("Hello, world!");
which is the same as writing this:
SafeString greeting = "Hello, world!";
2. I can't assign anything to a SafeString at the moment. I declared
the self-assignment operator private in the class definition above in
order to prevent the compiler from creating one for me that would have
just copied the psi pointer, which is definitely the wrong thing to do.
Assuming that StringInterface can manipulate a mutable string it must
provide some way to copy one string to another. I'll change my class to
add an assigment operator using that method:
SafeString& operator=(const StringInterface& rhs)
{
if (!psi) throw(something...);
// Assuming StringInterface::assign(const StringInterface &)
psi->assign(rhs);
}
This now means I can write this:
SafeString greeting = "Hello";
SafeString reply = StringFactory(...); // something mutable
reply = greeting;
Note that there's no copy constructor for SafeString, so I definitely
can't write this:
SafeString greeting = "Hello";
SafeString reply = greeting; // Link error, not implemented
The copy constructor for reply would have no way to tell what kind of
string I want it to instantiate. If StringInterface provided a clone()
method I could implement a copy constructor to clone the StringInterface
object that it's copying, but if it doesn't then the above code will
always have to give a link error. For the purposes of the current
argument I don't really care about that, but it's something to bear in mind.
Ok, so I've now defined a class that implements and uses our agreed
StringInterface API. It's exactly the same size as a StringInterface
pointer, but my class is safe from memory leaks and is more friendly to
users. Which should we encourage EPICS V4 users to develop with -
StringInterface pointers, or my SafeString class?
Now please compare SafeString to the overall shape of the definition of
EpicsString as found in the Wiki page "V4 Design: epicsTypes" at
http://www.aps.anl.gov/epics/wiki/index.php/V4_Design:_epicsTypes#epicsString
I would be happy to discuss changes to (or even a complete replacement
for) the EpicsBuffer interface which EpicsString was based on, and
changes to the methods of EpicsString itself. We can talk about whether
an EpicsString IS an EpicsBuffer, HAS an EpicsBuffer or even
IS-IMPLEMENTED-IN-TERMS-OF an EpicsBuffer (EffC++), but I will not
accept a standard string class which is just a pure virtual interface.
I hope the above discussion shows why.
Jeff, I'll be commenting on your reply in a separate message.
- Andrew
PS: Why aren't we discussing this on core-talk?
--
Podiabombastic: The tendency to shoot oneself in the foot.
- Navigate by Date:
- Prev:
[Fwd: RE: Standard String] Marty Kraimer
- Next:
[Fwd: Re: Standard String] Marty Kraimer
- Index:
2002
2003
2004
<2005>
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
RE: [Fwd: RE: Standard String] Jeff Hill
- Next:
[Fwd: Re: Standard String] Marty Kraimer
- Index:
2002
2003
2004
<2005>
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|