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:
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.
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).