mirror of
https://github.com/boostorg/static_string.git
synced 2026-01-19 04:42:12 +00:00
Make basic_static_string usable as a NTTP
This commit is contained in:
committed by
Gennaro Prota
parent
3a410b8472
commit
67efdf6a9b
@@ -314,103 +314,125 @@ copy_with_traits(
|
||||
template<std::size_t N, typename CharT, typename Traits>
|
||||
class static_string_base
|
||||
{
|
||||
private:
|
||||
using derived_type = basic_static_string<N, CharT, Traits>;
|
||||
friend derived_type;
|
||||
|
||||
using size_type = smallest_width<N>;
|
||||
using value_type = typename Traits::char_type;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
public:
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
static_string_base() noexcept { };
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
pointer
|
||||
data_impl() noexcept
|
||||
struct size
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
class basic_static_string
|
||||
{
|
||||
friend derived_type;
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
const_pointer
|
||||
data_impl() const noexcept
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
size_type
|
||||
size_impl() const noexcept
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
size_type
|
||||
size_impl(std::size_t n) noexcept
|
||||
{
|
||||
// Functions that set size will throw
|
||||
// if the new size would exceed max_size()
|
||||
// therefore we can guarantee that this will
|
||||
// not lose data.
|
||||
return size = static_cast<size_type>(n);
|
||||
}
|
||||
|
||||
public:
|
||||
size_type size = 0;
|
||||
};
|
||||
};
|
||||
|
||||
struct data
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
class basic_static_string
|
||||
{
|
||||
friend derived_type;
|
||||
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
std::size_t
|
||||
size_impl() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
pointer
|
||||
data_impl() noexcept
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
std::size_t
|
||||
set_size(std::size_t n) noexcept
|
||||
{
|
||||
// Functions that set size will throw
|
||||
// if the new size would exceed max_size()
|
||||
// therefore we can guarantee that this will
|
||||
// not lose data.
|
||||
return size_ = size_type(n);
|
||||
}
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
const_pointer
|
||||
data_impl() const noexcept
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
void
|
||||
term_impl() noexcept
|
||||
{
|
||||
Traits::assign(data_[size_], value_type());
|
||||
}
|
||||
|
||||
size_type size_ = 0;
|
||||
|
||||
value_type data_[N + 1]{};
|
||||
public:
|
||||
value_type data[N + 1]{};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// Optimization for when the size is 0
|
||||
template<typename CharT, typename Traits>
|
||||
class static_string_base<0, CharT, Traits>
|
||||
{
|
||||
private:
|
||||
using derived_type = basic_static_string<0, CharT, Traits>;
|
||||
friend derived_type;
|
||||
|
||||
using size_type = std::size_t;
|
||||
using value_type = typename Traits::char_type;
|
||||
using pointer = value_type*;
|
||||
public:
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
static_string_base() noexcept { }
|
||||
|
||||
// Modifying the null terminator is UB
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
pointer
|
||||
data_impl() const noexcept
|
||||
struct size
|
||||
{
|
||||
return const_cast<pointer>(&null_);
|
||||
}
|
||||
class basic_static_string
|
||||
{
|
||||
friend derived_type;
|
||||
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
std::size_t
|
||||
size_impl() const noexcept
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
size_type
|
||||
size_impl() const noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
size_type
|
||||
size_impl(std::size_t) const noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct data
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
class basic_static_string
|
||||
{
|
||||
friend derived_type;
|
||||
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
std::size_t
|
||||
set_size(std::size_t) const noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||
pointer
|
||||
data_impl() const noexcept
|
||||
{
|
||||
return const_cast<pointer>(&data);
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
void
|
||||
term_impl() const noexcept { }
|
||||
|
||||
private:
|
||||
static constexpr const value_type null_{};
|
||||
public:
|
||||
static constexpr value_type data{};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// This is only needed in C++14 and lower.
|
||||
// see http://eel.is/c++draft/depr.static.constexpr
|
||||
#ifndef BOOST_STATIC_STRING_CPP17
|
||||
#if 0
|
||||
template<typename CharT, typename Traits>
|
||||
constexpr
|
||||
const
|
||||
@@ -419,6 +441,13 @@ static_string_base<0, CharT, Traits>::
|
||||
null_;
|
||||
#endif
|
||||
|
||||
template<typename CharT, typename Traits>
|
||||
constexpr
|
||||
typename static_string_base<0, CharT, Traits>::value_type
|
||||
static_string_base<0, CharT, Traits>::data::basic_static_string::data;
|
||||
#endif
|
||||
|
||||
|
||||
template<typename CharT, typename Traits>
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
inline
|
||||
@@ -1054,7 +1083,11 @@ template<std::size_t N, typename CharT,
|
||||
typename Traits = std::char_traits<CharT>>
|
||||
class basic_static_string
|
||||
#ifndef BOOST_STATIC_STRING_DOCS
|
||||
: private detail::static_string_base<N, CharT, Traits>
|
||||
// : public detail::static_string_base<N, CharT, Traits>
|
||||
: public detail::static_string_base<
|
||||
N, CharT, Traits>::size::basic_static_string
|
||||
, public detail::static_string_base<
|
||||
N, CharT, Traits>::data::basic_static_string
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
@@ -2339,7 +2372,7 @@ public:
|
||||
void
|
||||
clear() noexcept
|
||||
{
|
||||
this->set_size(0);
|
||||
this->size_impl(0);
|
||||
term();
|
||||
}
|
||||
|
||||
@@ -2931,7 +2964,7 @@ public:
|
||||
pop_back() noexcept
|
||||
{
|
||||
BOOST_STATIC_STRING_ASSERT(!empty());
|
||||
this->set_size(size() - 1);
|
||||
this->size_impl(size() - 1);
|
||||
term();
|
||||
}
|
||||
|
||||
@@ -3107,7 +3140,7 @@ public:
|
||||
InputIterator first,
|
||||
InputIterator last)
|
||||
{
|
||||
this->set_size(size() + read_back(true, first, last));
|
||||
this->size_impl(size() + read_back(true, first, last));
|
||||
return term();
|
||||
}
|
||||
|
||||
@@ -5584,11 +5617,22 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
void term_impl(std::true_type) noexcept
|
||||
{
|
||||
traits_type::assign(data()[size()], value_type());
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
void term_impl(std::false_type) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_STATIC_STRING_CPP14_CONSTEXPR
|
||||
basic_static_string&
|
||||
term() noexcept
|
||||
{
|
||||
this->term_impl();
|
||||
term_impl(std::integral_constant<bool, N != 0>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -5596,7 +5640,7 @@ private:
|
||||
basic_static_string&
|
||||
assign_char(value_type ch, std::true_type) noexcept
|
||||
{
|
||||
this->set_size(1);
|
||||
this->size_impl(1);
|
||||
traits_type::assign(data()[0], ch);
|
||||
return term();
|
||||
}
|
||||
@@ -5670,7 +5714,7 @@ private:
|
||||
const_pointer s,
|
||||
size_type count) noexcept
|
||||
{
|
||||
this->set_size(count);
|
||||
this->size_impl(count);
|
||||
traits_type::copy(data(), s, size() + 1);
|
||||
return *this;
|
||||
}
|
||||
@@ -6591,7 +6635,7 @@ assign(
|
||||
if (count > max_size())
|
||||
detail::throw_exception<std::length_error>(
|
||||
"count > max_size()");
|
||||
this->set_size(count);
|
||||
this->size_impl(count);
|
||||
traits_type::assign(data(), size(), ch);
|
||||
return term();
|
||||
}
|
||||
@@ -6608,7 +6652,7 @@ assign(
|
||||
if (count > max_size())
|
||||
detail::throw_exception<std::length_error>(
|
||||
"count > max_size()");
|
||||
this->set_size(count);
|
||||
this->size_impl(count);
|
||||
traits_type::move(data(), s, size());
|
||||
return term();
|
||||
}
|
||||
@@ -6630,13 +6674,13 @@ assign(
|
||||
{
|
||||
if (i >= max_size())
|
||||
{
|
||||
this->set_size(i);
|
||||
this->size_impl(i);
|
||||
term();
|
||||
detail::throw_exception<std::length_error>("n > max_size()");
|
||||
}
|
||||
traits_type::assign(*ptr, *first);
|
||||
}
|
||||
this->set_size(ptr - data());
|
||||
this->size_impl(ptr - data());
|
||||
return term();
|
||||
}
|
||||
|
||||
@@ -6658,7 +6702,7 @@ insert(
|
||||
const auto index = pos - curr_data;
|
||||
traits_type::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1);
|
||||
traits_type::assign(&curr_data[index], count, ch);
|
||||
this->set_size(curr_size + count);
|
||||
this->size_impl(curr_size + count);
|
||||
return &curr_data[index];
|
||||
}
|
||||
|
||||
@@ -6711,7 +6755,7 @@ insert(
|
||||
traits_type::copy(dest, src, count);
|
||||
}
|
||||
}
|
||||
this->set_size(curr_size + count);
|
||||
this->size_impl(curr_size + count);
|
||||
return curr_data + index;
|
||||
}
|
||||
|
||||
@@ -6735,7 +6779,7 @@ insert(
|
||||
const auto count = read_back(false, first, last);
|
||||
const std::size_t index = pos - curr_data;
|
||||
std::rotate(&curr_data[index], &curr_data[curr_size + 1], &curr_data[curr_size + count + 1]);
|
||||
this->set_size(curr_size + count);
|
||||
this->size_impl(curr_size + count);
|
||||
return curr_data + index;
|
||||
}
|
||||
|
||||
@@ -6751,7 +6795,7 @@ erase(
|
||||
const auto curr_data = data();
|
||||
const std::size_t index = first - curr_data;
|
||||
traits_type::move(&curr_data[index], last, (end() - last) + 1);
|
||||
this->set_size(size() - std::size_t(last - first));
|
||||
this->size_impl(size() - std::size_t(last - first));
|
||||
return curr_data + index;
|
||||
}
|
||||
|
||||
@@ -6767,7 +6811,7 @@ push_back(
|
||||
detail::throw_exception<std::length_error>(
|
||||
"curr_size >= max_size()");
|
||||
traits_type::assign(data()[curr_size], ch);
|
||||
this->set_size(curr_size + 1);
|
||||
this->size_impl(curr_size + 1);
|
||||
term();
|
||||
}
|
||||
|
||||
@@ -6785,7 +6829,7 @@ append(
|
||||
detail::throw_exception<std::length_error>(
|
||||
"count > max_size() - size()");
|
||||
traits_type::assign(end(), count, ch);
|
||||
this->set_size(curr_size + count);
|
||||
this->size_impl(curr_size + count);
|
||||
return term();
|
||||
}
|
||||
|
||||
@@ -6803,7 +6847,7 @@ append(
|
||||
detail::throw_exception<std::length_error>(
|
||||
"count > max_size() - size()");
|
||||
traits_type::copy(end(), s, count);
|
||||
this->set_size(curr_size + count);
|
||||
this->size_impl(curr_size + count);
|
||||
return term();
|
||||
}
|
||||
|
||||
@@ -6819,7 +6863,7 @@ resize(size_type n, value_type c)
|
||||
const auto curr_size = size();
|
||||
if(n > curr_size)
|
||||
traits_type::assign(data() + curr_size, n - curr_size, c);
|
||||
this->set_size(n);
|
||||
this->size_impl(n);
|
||||
term();
|
||||
}
|
||||
|
||||
@@ -6839,7 +6883,7 @@ resize_and_overwrite(
|
||||
CharT* p = data();
|
||||
const auto new_size = std::move(op)(p, n);
|
||||
BOOST_STATIC_STRING_ASSERT(new_size >= 0 && size_type(new_size) <= n);
|
||||
this->set_size(size_type(new_size));
|
||||
this->size_impl(size_type(new_size));
|
||||
term();
|
||||
}
|
||||
|
||||
@@ -6851,9 +6895,9 @@ swap(basic_static_string& s) noexcept
|
||||
{
|
||||
const auto curr_size = size();
|
||||
basic_static_string tmp(s);
|
||||
s.set_size(curr_size);
|
||||
s.size_impl(curr_size);
|
||||
traits_type::copy(&s.data()[0], data(), curr_size + 1);
|
||||
this->set_size(tmp.size());
|
||||
this->size_impl(tmp.size());
|
||||
traits_type::copy(data(), tmp.data(), size() + 1);
|
||||
}
|
||||
|
||||
@@ -6872,10 +6916,8 @@ swap(basic_static_string<M, CharT, Traits>& s)
|
||||
detail::throw_exception<std::length_error>(
|
||||
"s.size() > max_size()");
|
||||
basic_static_string tmp(s);
|
||||
s.set_size(curr_size);
|
||||
traits_type::copy(&s.data()[0], data(), curr_size + 1);
|
||||
this->set_size(tmp.size());
|
||||
traits_type::copy(data(), &tmp.data()[0], size() + 1);
|
||||
s.assign_unchecked(data(), curr_size);
|
||||
assign_unchecked(tmp.data(), tmp.size());
|
||||
}
|
||||
|
||||
template<std::size_t N, typename CharT, typename Traits>
|
||||
@@ -6898,7 +6940,7 @@ replace(
|
||||
const auto pos = i1 - curr_data;
|
||||
traits_type::move(&curr_data[pos + n], i2, (end() - i2) + 1);
|
||||
traits_type::assign(&curr_data[pos], n, c);
|
||||
this->set_size((curr_size - n1) + n);
|
||||
this->size_impl((curr_size - n1) + n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -6959,7 +7001,7 @@ replace(
|
||||
traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
|
||||
}
|
||||
}
|
||||
this->set_size((curr_size - n1) + n2);
|
||||
this->size_impl((curr_size - n1) + n2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -6991,7 +7033,7 @@ replace(
|
||||
// Move everything from the end of the splice point to the end of the rotated string to
|
||||
// the begining of the splice point
|
||||
traits_type::move(&curr_data[pos + n2], &curr_data[pos + n2 + n1], ((curr_size - n1) + n2) - pos);
|
||||
this->set_size((curr_size - n1) + n2);
|
||||
this->size_impl((curr_size - n1) + n2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -7163,7 +7205,7 @@ replace_unchecked(
|
||||
"replaced string exceeds max_size()");
|
||||
traits_type::move(&curr_data[pos + n2], i2, (end() - i2) + 1);
|
||||
traits_type::copy(&curr_data[pos], s, n2);
|
||||
this->set_size((curr_size - n1) + n2);
|
||||
this->size_impl((curr_size - n1) + n2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -7185,7 +7227,7 @@ insert_unchecked(
|
||||
const std::size_t index = pos - curr_data;
|
||||
traits_type::move(&curr_data[index + count], pos, (end() - pos) + 1);
|
||||
traits_type::copy(&curr_data[index], s, count);
|
||||
this->set_size(curr_size + count);
|
||||
this->size_impl(curr_size + count);
|
||||
return curr_data + index;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,6 @@
|
||||
namespace boost {
|
||||
namespace static_strings {
|
||||
|
||||
static_assert(std::is_base_of<
|
||||
detail::static_string_base<0, char, std::char_traits<char>>,
|
||||
static_string<0>>::value,
|
||||
"the zero size optimization shall be used for N = 0");
|
||||
|
||||
static_assert(std::is_base_of<
|
||||
detail::static_string_base<(std::numeric_limits<char>::max)() + 1, char, std::char_traits<char>>,
|
||||
static_string<(std::numeric_limits<char>::max)() + 1>>::value,
|
||||
"the minimum size type optimization shall be used for N > 0");
|
||||
|
||||
static_assert(!detail::is_input_iterator<int>::value, "is_input_iterator is incorrect");
|
||||
static_assert(!detail::is_input_iterator<double>::value, "is_input_iterator is incorrect");
|
||||
static_assert(detail::is_input_iterator<int*>::value, "is_input_iterator is incorrect");
|
||||
|
||||
@@ -22,38 +22,74 @@ struct cxper_char_traits
|
||||
using int_type = int;
|
||||
using state_type = std::mbstate_t;
|
||||
|
||||
static constexpr void assign(char_type& a, const char_type& b) noexcept { a = b; }
|
||||
static constexpr bool eq(char_type a, char_type b) noexcept { return a == b; }
|
||||
static constexpr bool lt(char_type a, char_type b) noexcept { return a < b; }
|
||||
static constexpr void assign(char_type& a, const char_type& b) noexcept
|
||||
{
|
||||
a = b;
|
||||
}
|
||||
|
||||
static constexpr bool eq(char_type a, char_type b) noexcept
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
static constexpr bool lt(char_type a, char_type b) noexcept
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
static constexpr int compare(const char_type* a, const char_type* b, std::size_t n)
|
||||
{
|
||||
for (; n--; ++a, ++b)
|
||||
{
|
||||
if(lt(*a, *b))
|
||||
return 1;
|
||||
else if(lt(*b, *a))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr int compare(const char_type*, const char_type*, std::size_t) { return 0; }
|
||||
static constexpr std::size_t length(const char_type* s)
|
||||
{
|
||||
std::size_t n = 0;
|
||||
while (*(s++));
|
||||
return n;
|
||||
auto ptr = s;
|
||||
while (!eq(*ptr, char_type()))
|
||||
++ptr;
|
||||
return ptr - s;
|
||||
}
|
||||
static constexpr const char_type* find(const char_type*, std::size_t, const char_type&){ return 0; }
|
||||
|
||||
static constexpr const char_type* find(const char_type* s, std::size_t n, const char_type& ch)
|
||||
{
|
||||
for (; n--; ++s)
|
||||
{
|
||||
if (eq(*s, ch))
|
||||
return s;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static constexpr char_type* move(char_type* dest, const char_type* src, std::size_t n)
|
||||
{
|
||||
const auto temp = dest;
|
||||
while (n--)
|
||||
*(dest++) = *(src++);
|
||||
return temp;
|
||||
if (detail::ptr_in_range(src, src + n, dest))
|
||||
{
|
||||
while (n--)
|
||||
assign(dest[n], src[n]);
|
||||
return dest;
|
||||
}
|
||||
return copy(dest, src, n);
|
||||
}
|
||||
|
||||
static constexpr char_type* copy(char_type* dest, const char_type* src, std::size_t n)
|
||||
{
|
||||
const auto temp = dest;
|
||||
while (n--)
|
||||
*(dest++) = *(src++);
|
||||
return temp;
|
||||
for (auto ptr = dest; n--;)
|
||||
assign(*ptr++, *src++);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static constexpr char_type* assign(char_type* dest, std::size_t n, char_type ch)
|
||||
{
|
||||
const auto temp = dest;
|
||||
while (n--)
|
||||
*(dest++) = ch;
|
||||
return temp;
|
||||
for (auto ptr = dest; n--;)
|
||||
assign(*ptr++, ch);
|
||||
return dest;
|
||||
}
|
||||
};
|
||||
#else
|
||||
@@ -623,5 +659,28 @@ testConstantEvaluation()
|
||||
cstatic_string().empty();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_STATIC_STRING_CPP20
|
||||
|
||||
template<basic_static_string<32, char, cxper_char_traits> X>
|
||||
struct nttp_primary
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct nttp_primary<"test string">
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
static_assert(!nttp_primary<"random string">::value,
|
||||
"structural equality broken");
|
||||
|
||||
static_assert(nttp_primary<"test string">::value,
|
||||
"structural equality broken");
|
||||
|
||||
#endif
|
||||
|
||||
} // static_strings
|
||||
} // boost
|
||||
|
||||
Reference in New Issue
Block a user