patterncppMinor
Short string class
Viewed 0 times
classstringshort
Problem
On one of the projects I'm working on, we have many objects that store (small) strings, loaded from database. I know
This is not meant as a replacement for
Basic functionality is provided to allow interoperability (to some degree) with
How it works:
It stores remaining capacity (a very clever trick by Andrei Alexandrescu, nicely explained here). When creating/appending larger strings than the capacity, data is truncated instead of throwing an exception, for performance reasons.
```
#pragma once
#include
#include // ostream operator // memcpy
template
class ShortString {
public:
using size_type = std::size_t;
using value_type = T;
constexpr ShortString() noexcept
: _buffer{}
{
set_size(0u);
}
template
constexpr ShortString(const T(&str)[N]) noexcept
: _buffer{}
{
auto size = N >= Size ? Size - 1 : N - 1;
std::memcpy(_buffer, str, size);
set_size(size);
}
template
ShortString(const std::basic_string& str) noexcept
: _buffer{}
{
auto size = str.size() >= Size ? Size : str.size();
std::memcpy(_buffer, str.c_str(), size);
set_size(size);
}
template
constexpr ShortString(const ShortString& rhs) noexcept
: _buffer{}
{
auto size = N >= Size ? Size : N;
std::memcpy(_buffer, rhs.c_str(), size);
set_size(size);
}
template
constexpr ShortString& operator = (const T(&str)[N]) noexcept {
auto size = N >= Size ? Size - 1 : N - 1;
std::memcpy(_buffer, str, size);
set_size(size);
return *th
std::string's have small string optimization (SSO), but the overhead, in my opinion, is too big; most strings are < 16 characters, and on my platform sizeof(std::string) is 32, wasting 50% of memory. Also less data == less work.This is not meant as a replacement for
std::string, but to be used in places where one can guarantee the size of string won't exceed capacity.Basic functionality is provided to allow interoperability (to some degree) with
std::string.How it works:
It stores remaining capacity (a very clever trick by Andrei Alexandrescu, nicely explained here). When creating/appending larger strings than the capacity, data is truncated instead of throwing an exception, for performance reasons.
```
#pragma once
#include
#include // ostream operator // memcpy
template
class ShortString {
public:
using size_type = std::size_t;
using value_type = T;
constexpr ShortString() noexcept
: _buffer{}
{
set_size(0u);
}
template
constexpr ShortString(const T(&str)[N]) noexcept
: _buffer{}
{
auto size = N >= Size ? Size - 1 : N - 1;
std::memcpy(_buffer, str, size);
set_size(size);
}
template
ShortString(const std::basic_string& str) noexcept
: _buffer{}
{
auto size = str.size() >= Size ? Size : str.size();
std::memcpy(_buffer, str.c_str(), size);
set_size(size);
}
template
constexpr ShortString(const ShortString& rhs) noexcept
: _buffer{}
{
auto size = N >= Size ? Size : N;
std::memcpy(_buffer, rhs.c_str(), size);
set_size(size);
}
template
constexpr ShortString& operator = (const T(&str)[N]) noexcept {
auto size = N >= Size ? Size - 1 : N - 1;
std::memcpy(_buffer, str, size);
set_size(size);
return *th
Solution
I feel like the implementation of the class would be simpler if backed by a
Initializing the buffer via
You're missing a very significant amount of the
Also I strongly disagree with the exception throwing vs truncation. Definitely throw exceptions. At least assert. There's no performance penalty for exceptions here on most compilers, except when it's hit.
std::array instead of value_type _buffer[Size];, because then you could use the standard algorithms (aka iterators) easier, and get bounds checking in debug builds (at least in MSVC). Initializing the buffer via
: _buffer{} is unnecessarily slowing you down for no reason in most of the constructors, since you proceed to fill in the buffer regardless.compare should be named operator==, so it's clear which comparison it's doing. I'd assumed it was operator>, also weird.You're missing a very significant amount of the
std::basic_string interface. Prefer to match the existing design patterns.Also I strongly disagree with the exception throwing vs truncation. Definitely throw exceptions. At least assert. There's no performance penalty for exceptions here on most compilers, except when it's hit.
Context
StackExchange Code Review Q#148757, answer score: 5
Revisions (0)
No revisions yet.