Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practice for Fixed Size String Class

I would like to have a fixed size string class. Ideally, the interface would match the one of std::string with the one difference that the new class never allocates new memory. It is supposed to be a handy class for application cases where allocating new memory should be avoided. The size can be static (known at compile time).

I think there are two ways. The first would be to implement a class around a char array and then implement more or less all the functions that the std::string has. I also would have to implement some operators to create std::strings with a given fixed size string, etc.

The second method, I'm not even sure is possible, would be to inherit from std::string and override all the functions that may change the size of the string. I looked into the basic_string header in Visual Studio and it doesn't seem to be virtual, so I guess this is not the way to go.

What would you say is the best approach for implementing such class?

like image 220
ruhig brauner Avatar asked Aug 26 '16 17:08

ruhig brauner


People also ask

How do you declare a string of fixed size?

The idea is to first, get the length L of the string is taken as input and then input the specific character C and initialize empty string str. Now, iterate a loop for L number of times. In every iteration, the specific character is concatenated with string str until the for loop ends.

What is max size of std::string?

While an individual quoted string cannot be longer than 2048 bytes, a string literal of roughly 65535 bytes can be constructed by concatenating strings.

How do you determine a string size?

You can get the length of a string object by using a size() function or a length() function. The size() and length() functions are just synonyms and they both do exactly same thing.


1 Answers

The first would be to implement a class around a char array and then implement more or less all the functions that the std::string has.

This is definitely the way to go. It's easy to write, easy to use, and difficult to misuse.

template <size_t N>
class fixed_string {
    char array[N+1];
    size_t size;

public:
    fixed_string() : size(0) { array[0] = '\0'; }

    // all the special members can be defaulted
    fixed_string(fixed_string const&) = default;
    fixed_string(fixed_string&&) = default;
    fixed_string& operator=(fixed_string const&) = default;
    fixed_string& operator=(fixed_string&&) = default;
    ~fixed_string() = default;

    // ...
};

All the accessors (data, c_str, begin, end, at, operator[]) are one-liners. All the search algorithms are straightforward.

The only real design question is what do you want the mutations to do on failure. That is:

fixed_string<5> foo("abcde");
foo += 'f'; // assert? throw? range-check internally and ignore?
            // just not even add this and instead write a 
            // try_append() that returns optional<fixed_string&>?

There are advantages and disadvantages to design choice, but regardless of which one you pick, the implementation of each function is also going to be very concise.


The second method, I'm not even sure is possible, would be to inherit from std::string and override all the functions that may change the size of the string. I looked into the basic_string header in Visual Studio and it doesn't seem to be virtual, so I guess this is not the way to go.

Whether or not anything in std::string is virtual is irrelevant to the question of whether or not this is a good idea. You would definitely want to start from:

template <size_t N>
class fixed_string : private std::string { ... }
//                  ^^^^^^^^^

Since your type would definitely not fit the is-a relationship with std::string. It's not a std::string, it'd merely be implemented in terms of it. Private inheritance would make this code ill-formed:

std::string* p = new fixed_string<5>();

so you don't have to worry about lack of virtual.

That said, inheriting from string is going to make for a much more complicated, less efficient implementation than just going the direct route, with way more potential pitfalls. It's probably possible to implement such a thing, but I can't see how it would be a good idea.

like image 183
Barry Avatar answered Oct 24 '22 09:10

Barry