4

I need to implement a C++11 or C++14 type STRING that acts just like std:string, but has the following additional constraints/features:

  1. WIDTH parameter specified during declaration. STRING will throw exception if its length is greater than WIDTH
  2. Optional FIXED parameter specified during declaration. STRING will throw exception if its length is not equal to WIDTH

In all other respects, STRING is supposed to behave just like std::string and expose the same member functions as std:string (such as .append() etc..).

My first instinct was to use a template class STRING that holds a std::string, like so:

template<int WIDTH= 0, bool FIXED = false>
class STRING {
    static_assert(WIDTH >= 0, "WIDTH of STRING cannot be negative.");
public:
    STRING() : value{} { }

    STRING(const std::string &s) { if (is_valid(s)) value = s; }

    STRING(const char c[]) { if (is_valid(c)) value = c; }

    STRING& operator=(const std::string& s){ if (is_valid(s)) value = s;}
    operator std::string() const { return value; }


    std::string value;

private:
    bool is_valid(const std::string &s) {
        if (WIDTH && s.length() > WIDTH)
            throw std::length_error{"STRING assignment failed. STRING too long."};
        if (FIXED && s.length() != WIDTH)
            throw std::length_error{"STRING assignment failed. STRING has wrong length."};
        return true;
    }
};

However, the above STRING template class does not expose std::string member functions and I do not want to re-implement the entire std::basic_char function set, so I think my approach is fundamentally wrong. I suspect somehow extending std::string might be better, but it seems a little scary to "mess" with the standard library types.

I am not sure what the best approach would be here and pointers in the right direction would be more than welcome.

9
  • What happens to the width when you need to do something like string1 + string2? Commented Jan 26, 2016 at 20:36
  • Your first instinct is right (please make std::string value; private). You observe the ugliness of a string class based on std::string, exposing the same (and extended) functionality. Commented Jan 26, 2016 at 20:38
  • @user2357112: Adding a STRING<7> and a STRING<5> creates a STRING<12>, obviously. The "fixed" bit is slightly less obvious: the result is fixed if and only if both inputs are fixed. Commented Jan 26, 2016 at 22:43
  • @MSalters: See, that might be obvious from your perspective, but to someone with a different use case in mind, it might be obvious that adding a STRING<7> and a STRING<7> produces another STRING<7> and adding a STRING<7> and a STRING<5> is a compile-time error. Commented Jan 26, 2016 at 22:54
  • @user2357112: There's a strong consensus, even across programming languages that if strings have a binary operator +, then it's concatenation. Famously, Java has only case of operator overloading, and it's String+String Python too uses +. Commented Jan 26, 2016 at 22:57

1 Answer 1

5

The easiest way to accomplish this is through modifying the allocator template argument. Note that std::string is a shorthand for

std::basic_string<char, std::char_traits<char>, std::allocator<char>>

Inside the allocator you can put functionality to check for overflow or length.

Look at this Q&A on advice on how to write a custom allocator. Howard Hinnant's website has an example on how to limit the boilerplate you need to duplicate.

As remarked by @rici, most implementations will use the short-string-optimization (SSO). This means that the string class will have a union of a small stack-based storage (typically 24 bytes or so) and three pointers into the heap. This means that for small strings, the supplied allocator maybe ignored altogether. That would in practice mean that you could not limit strings to be very small (below the SSO threshold).

Sign up to request clarification or add additional context in comments.

2 Comments

And short string optimization means there might not be an allocation.
@rici: thanks for your helpful comment. I will think of a different solution for my use case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.