Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I need some C++ guru's opinions on extending std::string

Tags:

c++

stl

subclass

I've always wanted a bit more functionality in STL's string. Since subclassing STL types is a no no, mostly I've seen the recommended method of extension of these classes is just to write functions (not member functions) that take the type as the first argument.

I've never been thrilled with this solution. For one, it's not necessarily obvious where all such methods are in the code, for another, I just don't like the syntax. I want to use . when I call methods!

A while ago I came up with the following:

class StringBox
{
public:
   StringBox( std::string& storage ) :
       _storage( storage )
   {
   }

   // Methods I wish std::string had...
   void Format(); 
   void Split();
   double ToDouble(); 
   void Join(); // etc...

private:
  StringBox();

  std::string& _storage;
};

Note that StringBox requires a reference to a std::string for construction... This puts some interesting limits on it's use (and I hope, means it doesn't contribute to the string class proliferation problem)... In my own code, I'm almost always just declaring it on the stack in a method, just to modify a std::string.

A use example might look like this:

string OperateOnString( float num, string a, string b )
{
    string nameS;
    StringBox name( nameS );

    name.Format( "%f-%s-%s", num, a.c_str(), b.c_str() );

    return nameS;
}

My question is: What do the C++ guru's of the StackOverflow community think of this method of STL extension?

like image 992
dicroce Avatar asked Jan 10 '10 17:01

dicroce


People also ask

How do you extend a string in C++?

C++ String append() This function is used to extend the string by appending at the end of the current value.

Can you use std::string in C?

The std::string class manages the underlying storage for you, storing your strings in a contiguous manner. You can get access to this underlying buffer using the c_str() member function, which will return a pointer to null-terminated char array. This allows std::string to interoperate with C-string APIs.

How many bytes is a std::string?

While std::string has the size of 24 bytes, it allows strings up to 22 bytes(!!) with no allocation.

What does std::string () do?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.


1 Answers

I've never been thrilled with this solution. For one, it's not necessarily obvious where all such methods are in the code, for another, I just don't like the syntax. I want to use . when I call methods!

And I want to use $!---& when I call methods! Deal with it. If you're going to write C++ code, stick to C++ conventions. And a very important C++ convention is to prefer non-member functions when possible.

There is a reason C++ gurus recommend this:

It improves encapsulation, extensibility and reuse. (std::sort can work with all iterator pairs because it isn't a member of any single iterator or container class. And no matter how you extend std::string, you can not break it, as long as you stick to non-member functions. And even if you don't have access to, or aren't allowed to modify, the source code for a class, you can still extend it by defining nonmember functions)

Personally, I can't see the point in your code. Isn't this a lot simpler, more readable and shorter?

string OperateOnString( float num, string a, string b )
{
    string nameS;
    Format(nameS, "%f-%s-%s", num, a.c_str(), b.c_str() );
    return nameS;
}

// or even better, if `Format` is made to return the string it creates, instead of taking it as a parameter
string OperateOnString( float num, string a, string b )
{
    return Format("%f-%s-%s", num, a.c_str(), b.c_str() );
}

When in Rome, do as the Romans, as the saying goes. Especially when the Romans have good reasons to do as they do. And especially when your own way of doing it doesn't actually have a single advantage. It is more error-prone, confusing to people reading your code, non-idiomatic and it is just more lines of code to do the same thing.

As for your problem that it's hard to find the non-member functions that extend string, place them in a namespace if that's a concern. That's what they're for. Create a namespace StringUtil or something, and put them there.

like image 62
jalf Avatar answered Sep 20 '22 18:09

jalf