mirror of
https://github.com/boostorg/static_string.git
synced 2026-08-29 08:02:19 +02:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ff9d3535e | ||
|
|
8c44a96c8d | ||
|
|
bf20b809ec | ||
|
|
9271183ea8 | ||
|
|
1c3143c18b | ||
|
|
62ed5ee17a | ||
|
|
c6cd8074ab | ||
|
|
54eda39d91 | ||
|
|
e9313dc331 | ||
|
|
0c5e5b8e58 | ||
|
|
6f0c00b268 | ||
|
|
2175496c55 | ||
|
|
aee3c62957 | ||
|
|
0e28b358dc | ||
|
|
4dcfb39494 | ||
|
|
4bf6461ca1 | ||
|
|
67efdf6a9b | ||
|
|
3a410b8472 |
+128
-10
@@ -25,14 +25,132 @@ on:
|
|||||||
- meta/**
|
- meta/**
|
||||||
- README.md
|
- README.md
|
||||||
|
|
||||||
env:
|
|
||||||
B2_TARGETS: libs/$SELF/example
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
call-boost-ci:
|
linux:
|
||||||
name: Run Boost.CI
|
runs-on: ubuntu-24.04
|
||||||
uses: boostorg/boost-ci/.github/workflows/reusable.yml@master
|
strategy:
|
||||||
with:
|
fail-fast: false
|
||||||
exclude_cxxstd: '98,03,0x,11,14,17'
|
matrix:
|
||||||
enable_pr_coverage: false
|
include:
|
||||||
enable_multiarch: false
|
- { toolset: gcc-13, cxxstd: '20,23' }
|
||||||
|
- { toolset: gcc-14, cxxstd: '20,23,26' }
|
||||||
|
- { toolset: clang-17, cxxstd: '20,23' }
|
||||||
|
- { toolset: clang-18, cxxstd: '20,23,26' }
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Boost super-project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: boostorg/boost
|
||||||
|
ref: develop
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Checkout this library
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: libs/static_string
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Initialize Boost submodules
|
||||||
|
run: |
|
||||||
|
git submodule update --init tools/boostdep
|
||||||
|
python tools/boostdep/depinst/depinst.py --git_args '--jobs 4' static_string
|
||||||
|
|
||||||
|
- name: Bootstrap b2
|
||||||
|
run: ./bootstrap.sh
|
||||||
|
|
||||||
|
- name: Generate Boost headers
|
||||||
|
run: ./b2 headers
|
||||||
|
|
||||||
|
- name: Build and run example tests
|
||||||
|
run: |
|
||||||
|
./b2 libs/static_string/example/static_cstring \
|
||||||
|
toolset=${{ matrix.toolset }} \
|
||||||
|
cxxstd=${{ matrix.cxxstd }} \
|
||||||
|
variant=debug,release \
|
||||||
|
-j$(nproc)
|
||||||
|
|
||||||
|
macos:
|
||||||
|
runs-on: macos-14
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- { toolset: clang, cxxstd: '20,23' }
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Boost super-project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: boostorg/boost
|
||||||
|
ref: develop
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Checkout this library
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: libs/static_string
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Initialize Boost submodules
|
||||||
|
run: |
|
||||||
|
git submodule update --init tools/boostdep
|
||||||
|
python3 tools/boostdep/depinst/depinst.py --git_args '--jobs 4' static_string
|
||||||
|
|
||||||
|
- name: Bootstrap b2
|
||||||
|
run: ./bootstrap.sh
|
||||||
|
|
||||||
|
- name: Generate Boost headers
|
||||||
|
run: ./b2 headers
|
||||||
|
|
||||||
|
- name: Build and run example tests
|
||||||
|
run: |
|
||||||
|
./b2 libs/static_string/example/static_cstring \
|
||||||
|
toolset=${{ matrix.toolset }} \
|
||||||
|
cxxstd=${{ matrix.cxxstd }} \
|
||||||
|
variant=debug,release \
|
||||||
|
-j$(sysctl -n hw.ncpu)
|
||||||
|
|
||||||
|
windows:
|
||||||
|
runs-on: windows-2022
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- { toolset: msvc-14.3, cxxstd: '20,latest' }
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Boost super-project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: boostorg/boost
|
||||||
|
ref: develop
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Checkout this library
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: libs/static_string
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Initialize Boost submodules
|
||||||
|
run: |
|
||||||
|
git submodule update --init tools/boostdep
|
||||||
|
python tools/boostdep/depinst/depinst.py --git_args '--jobs 4' static_string
|
||||||
|
|
||||||
|
- name: Bootstrap b2
|
||||||
|
run: .\bootstrap.bat
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Generate Boost headers
|
||||||
|
run: .\b2 headers
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Build and run example tests
|
||||||
|
run: |
|
||||||
|
.\b2 libs/static_string/example/static_cstring ^
|
||||||
|
toolset=${{ matrix.toolset }} ^
|
||||||
|
cxxstd=${{ matrix.cxxstd }} ^
|
||||||
|
variant=debug,release ^
|
||||||
|
address-model=64
|
||||||
|
shell: cmd
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <boost/static_string/config.hpp>
|
#include <boost/static_string/config.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <compare>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -25,7 +26,7 @@ namespace static_strings {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// Primary template: No remaining-capacity trick; uses traits::length() for size.
|
// Primary template: No remaining-capacity trick; uses traits::length() for length.
|
||||||
template<std::size_t N, typename CharT, typename Traits, bool UseRemaining>
|
template<std::size_t N, typename CharT, typename Traits, bool UseRemaining>
|
||||||
class static_cstring_base
|
class static_cstring_base
|
||||||
{
|
{
|
||||||
@@ -45,18 +46,9 @@ public:
|
|||||||
{
|
{
|
||||||
data_[sz] = value_type{};
|
data_[sz] = value_type{};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void init_empty() noexcept
|
|
||||||
{
|
|
||||||
data_[0] = value_type{};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defaulted comparisons for structural type support.
|
|
||||||
constexpr bool operator==(const static_cstring_base&) const noexcept = default;
|
|
||||||
constexpr auto operator<=>(const static_cstring_base&) const noexcept = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for N <= UCHAR_MAX: Use remaining-capacity trick.
|
// Specialization for N <= UCHAR_MAX: Uses remaining-capacity trick.
|
||||||
template<std::size_t N, typename CharT, typename Traits>
|
template<std::size_t N, typename CharT, typename Traits>
|
||||||
class static_cstring_base<N, CharT, Traits, true>
|
class static_cstring_base<N, CharT, Traits, true>
|
||||||
{
|
{
|
||||||
@@ -77,16 +69,6 @@ public:
|
|||||||
data_[sz] = value_type{};
|
data_[sz] = value_type{};
|
||||||
data_[N] = static_cast<value_type>(N - sz);
|
data_[N] = static_cast<value_type>(N - sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void init_empty() noexcept
|
|
||||||
{
|
|
||||||
data_[0] = value_type{};
|
|
||||||
data_[N] = static_cast<value_type>(N);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defaulted comparisons for structural type support.
|
|
||||||
constexpr bool operator==(const static_cstring_base&) const noexcept = default;
|
|
||||||
constexpr auto operator<=>(const static_cstring_base&) const noexcept = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@@ -100,7 +82,6 @@ public:
|
|||||||
using base::data_;
|
using base::data_;
|
||||||
using base::get_size;
|
using base::get_size;
|
||||||
using base::set_size;
|
using base::set_size;
|
||||||
using base::init_empty;
|
|
||||||
|
|
||||||
// Member types
|
// Member types
|
||||||
using traits_type = Traits;
|
using traits_type = Traits;
|
||||||
@@ -120,7 +101,7 @@ public:
|
|||||||
// Constructors.
|
// Constructors.
|
||||||
constexpr basic_static_cstring() noexcept
|
constexpr basic_static_cstring() noexcept
|
||||||
{
|
{
|
||||||
init_empty();
|
set_size(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr basic_static_cstring(const CharT* s)
|
constexpr basic_static_cstring(const CharT* s)
|
||||||
@@ -141,8 +122,8 @@ public:
|
|||||||
template<std::size_t M>
|
template<std::size_t M>
|
||||||
constexpr basic_static_cstring(const CharT (&arr)[M])
|
constexpr basic_static_cstring(const CharT (&arr)[M])
|
||||||
{
|
{
|
||||||
static_assert(M <= N + 1, "String literal too long for static_cstring");
|
static_assert(M <= N + 1, "Array too big for static_cstring");
|
||||||
assign(arr, M - 1);
|
assign(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_type size() const noexcept
|
constexpr size_type size() const noexcept
|
||||||
@@ -201,21 +182,25 @@ public:
|
|||||||
|
|
||||||
constexpr reference front() noexcept
|
constexpr reference front() noexcept
|
||||||
{
|
{
|
||||||
|
BOOST_STATIC_STRING_ASSERT(!empty());
|
||||||
return data_[0];
|
return data_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_reference front() const noexcept
|
constexpr const_reference front() const noexcept
|
||||||
{
|
{
|
||||||
|
BOOST_STATIC_STRING_ASSERT(!empty());
|
||||||
return data_[0];
|
return data_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr reference back() noexcept
|
constexpr reference back() noexcept
|
||||||
{
|
{
|
||||||
|
BOOST_STATIC_STRING_ASSERT(!empty());
|
||||||
return data_[size() - 1];
|
return data_[size() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_reference back() const noexcept
|
constexpr const_reference back() const noexcept
|
||||||
{
|
{
|
||||||
|
BOOST_STATIC_STRING_ASSERT(!empty());
|
||||||
return data_[size() - 1];
|
return data_[size() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +253,7 @@ public:
|
|||||||
// Modifiers.
|
// Modifiers.
|
||||||
constexpr void clear() noexcept
|
constexpr void clear() noexcept
|
||||||
{
|
{
|
||||||
init_empty();
|
set_size(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr basic_static_cstring& assign(const CharT* s)
|
constexpr basic_static_cstring& assign(const CharT* s)
|
||||||
@@ -378,7 +363,17 @@ public:
|
|||||||
|
|
||||||
constexpr int compare(const CharT* s) const noexcept
|
constexpr int compare(const CharT* s) const noexcept
|
||||||
{
|
{
|
||||||
return compare(basic_static_cstring(s));
|
const size_type lhs_sz = size();
|
||||||
|
const size_type rhs_sz = traits_type::length(s);
|
||||||
|
const int result = traits_type::compare(data_, s, (std::min)(lhs_sz, rhs_sz));
|
||||||
|
|
||||||
|
return result != 0
|
||||||
|
? result
|
||||||
|
: lhs_sz < rhs_sz
|
||||||
|
? -1
|
||||||
|
: lhs_sz > rhs_sz
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conversions.
|
// Conversions.
|
||||||
@@ -400,9 +395,18 @@ public:
|
|||||||
other = tmp;
|
other = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaulted comparisons for structural type (C++20).
|
constexpr bool operator==(const basic_static_cstring& other) const noexcept
|
||||||
constexpr bool operator==(const basic_static_cstring&) const noexcept = default;
|
{
|
||||||
constexpr auto operator<=>(const basic_static_cstring&) const noexcept = default;
|
const size_type sz = size();
|
||||||
|
return sz == other.size()
|
||||||
|
&& traits_type::compare(data_, other.data_, sz) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::strong_ordering
|
||||||
|
operator<=>(const basic_static_cstring& other) const noexcept
|
||||||
|
{
|
||||||
|
return compare(other) <=> 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(BOOST_STATIC_STRING_USE_DEDUCT)
|
#if defined(BOOST_STATIC_STRING_USE_DEDUCT)
|
||||||
|
|||||||
@@ -75,41 +75,39 @@ testCStringRemainingCapacityTrick()
|
|||||||
large.assign(100, 'x');
|
large.assign(100, 'x');
|
||||||
BOOST_TEST(large.size() == 100);
|
BOOST_TEST(large.size() == 100);
|
||||||
BOOST_TEST(large.capacity() == UCHAR_MAX);
|
BOOST_TEST(large.capacity() == UCHAR_MAX);
|
||||||
BOOST_TEST(static_cast<unsigned char>(large.data()[UCHAR_MAX]) == (large.capacity() - large.size()));
|
BOOST_TEST(static_cast<unsigned char>(large.data()[UCHAR_MAX]) == (UCHAR_MAX - large.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename S>
|
||||||
|
struct CStringTypeTraits
|
||||||
|
{
|
||||||
|
static_assert(std::is_trivially_copyable<S>::value);
|
||||||
|
static_assert(std::is_trivially_copy_constructible<S>::value);
|
||||||
|
static_assert(std::is_trivially_move_constructible<S>::value);
|
||||||
|
static_assert(std::is_trivially_copy_assignable<S>::value);
|
||||||
|
static_assert(std::is_trivially_move_assignable<S>::value);
|
||||||
|
static_assert(std::is_trivially_destructible<S>::value);
|
||||||
|
};
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
testCStringTypeTraits()
|
testCStringTypeTraits()
|
||||||
{
|
{
|
||||||
// static_cstring should be trivially copyable for use in POD structs.
|
|
||||||
{
|
{
|
||||||
using S = static_cstring<0>;
|
using S = static_cstring<0>;
|
||||||
static_assert(std::is_trivially_copyable<S>::value, "");
|
CStringTypeTraits< S > check;
|
||||||
static_assert(std::is_trivially_copy_constructible<S>::value, "");
|
static_cast<void>(check);
|
||||||
static_assert(std::is_trivially_move_constructible<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_copy_assignable<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_move_assignable<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_destructible<S>::value, "");
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using S = static_cstring<63>;
|
using S = static_cstring<63>;
|
||||||
static_assert(std::is_trivially_copyable<S>::value, "");
|
CStringTypeTraits< S > check;
|
||||||
static_assert(std::is_trivially_copy_constructible<S>::value, "");
|
static_cast<void>(check);
|
||||||
static_assert(std::is_trivially_move_constructible<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_copy_assignable<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_move_assignable<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_destructible<S>::value, "");
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using S = static_cstring<300>;
|
using S = static_cstring<300>;
|
||||||
static_assert(std::is_trivially_copyable<S>::value, "");
|
CStringTypeTraits< S > check;
|
||||||
static_assert(std::is_trivially_copy_constructible<S>::value, "");
|
static_cast<void>(check);
|
||||||
static_assert(std::is_trivially_move_constructible<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_copy_assignable<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_move_assignable<S>::value, "");
|
|
||||||
static_assert(std::is_trivially_destructible<S>::value, "");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,6 +154,13 @@ testCStringConstruct()
|
|||||||
BOOST_TEST(*s1.end() == 0);
|
BOOST_TEST(*s1.end() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct from a C string with embedded NULs.
|
||||||
|
{
|
||||||
|
const char arr[] = { '1', '2', '\0', '4', '5', '\0' };
|
||||||
|
static_cstring<5> s1(arr);
|
||||||
|
BOOST_TEST(s1 == "12" );
|
||||||
|
}
|
||||||
|
|
||||||
// Copy construction.
|
// Copy construction.
|
||||||
{
|
{
|
||||||
static_cstring<5> s1("12345");
|
static_cstring<5> s1("12345");
|
||||||
@@ -445,6 +450,105 @@ testCStringComparison()
|
|||||||
BOOST_TEST(s.compare("abd") < 0);
|
BOOST_TEST(s.compare("abd") < 0);
|
||||||
BOOST_TEST(s.compare("abb") > 0);
|
BOOST_TEST(s.compare("abb") > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compare(const CharT*) must not throw when the argument is longer
|
||||||
|
// than the static capacity.
|
||||||
|
{
|
||||||
|
static_cstring<3> s("abc");
|
||||||
|
BOOST_TEST(s.compare("abcd") < 0);
|
||||||
|
BOOST_TEST(s.compare("abcdefghijklmnop") < 0);
|
||||||
|
BOOST_TEST(s.compare("abb") > 0);
|
||||||
|
BOOST_TEST(s.compare("abd") < 0);
|
||||||
|
BOOST_TEST(s.compare("abc") == 0);
|
||||||
|
BOOST_TEST(s.compare("ab") > 0);
|
||||||
|
BOOST_TEST(s.compare("") > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same via operator== / operator!= with an over-long C string.
|
||||||
|
{
|
||||||
|
static_cstring<3> s("abc");
|
||||||
|
BOOST_TEST(!(s == "abcd"));
|
||||||
|
BOOST_TEST(s != "abcd");
|
||||||
|
BOOST_TEST(!("abcd" == s));
|
||||||
|
BOOST_TEST("abcd" != s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty static_cstring vs non-empty C string.
|
||||||
|
{
|
||||||
|
static_cstring<5> empty;
|
||||||
|
BOOST_TEST(empty.compare("hello") < 0);
|
||||||
|
BOOST_TEST(empty.compare("") == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
testCStringComparisonAfterShrink()
|
||||||
|
{
|
||||||
|
// Two semantically equal strings must compare equal, even if one of
|
||||||
|
// them was first longer and then shrunk.
|
||||||
|
|
||||||
|
// Small-N path (remaining-capacity trick): shrinking assign(s, n).
|
||||||
|
{
|
||||||
|
static_cstring<10> s("hello");
|
||||||
|
s.assign("hi", 2);
|
||||||
|
static_cstring<10> fresh("hi");
|
||||||
|
|
||||||
|
BOOST_TEST(s == fresh);
|
||||||
|
BOOST_TEST(!(s != fresh));
|
||||||
|
BOOST_TEST(!(s < fresh));
|
||||||
|
BOOST_TEST(!(s > fresh));
|
||||||
|
BOOST_TEST(s <= fresh);
|
||||||
|
BOOST_TEST(s >= fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small-N path: shrinking assign(count, ch).
|
||||||
|
{
|
||||||
|
static_cstring<10> s("xxxxx");
|
||||||
|
s.assign(2, 'y');
|
||||||
|
static_cstring<10> fresh(2, 'y');
|
||||||
|
|
||||||
|
BOOST_TEST(s == fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small-N path: shrinking via operator=(const CharT*).
|
||||||
|
{
|
||||||
|
static_cstring<10> s("hello");
|
||||||
|
s = "hi";
|
||||||
|
static_cstring<10> fresh("hi");
|
||||||
|
|
||||||
|
BOOST_TEST(s == fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small-N path: shrinking via pop_back().
|
||||||
|
{
|
||||||
|
static_cstring<10> s("abcde");
|
||||||
|
s.pop_back();
|
||||||
|
static_cstring<10> fresh("abcd");
|
||||||
|
|
||||||
|
BOOST_TEST(s == fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Small-N path: shrinking via clear().
|
||||||
|
{
|
||||||
|
static_cstring<10> s("abcde");
|
||||||
|
s.clear();
|
||||||
|
static_cstring<10> fresh;
|
||||||
|
|
||||||
|
BOOST_TEST(s == fresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Large-N path (N > UCHAR_MAX, no remaining-capacity trick).
|
||||||
|
{
|
||||||
|
static_cstring<300> s;
|
||||||
|
s.assign(200, 'a');
|
||||||
|
s.assign(50, 'b');
|
||||||
|
static_cstring<300> fresh(50, 'b');
|
||||||
|
|
||||||
|
BOOST_TEST(s == fresh);
|
||||||
|
BOOST_TEST(!(s < fresh));
|
||||||
|
BOOST_TEST(!(s > fresh));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -652,6 +756,7 @@ runTests()
|
|||||||
testCStringPushPop();
|
testCStringPushPop();
|
||||||
testCStringAppend();
|
testCStringAppend();
|
||||||
testCStringComparison();
|
testCStringComparison();
|
||||||
|
testCStringComparisonAfterShrink();
|
||||||
testCStringConversion();
|
testCStringConversion();
|
||||||
testCStringStream();
|
testCStringStream();
|
||||||
testCStringSwap();
|
testCStringSwap();
|
||||||
|
|||||||
@@ -2314,6 +2314,23 @@ public:
|
|||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return the number of additional characters that can be stored.
|
||||||
|
|
||||||
|
Returns `max_size() - size()`, i.e. the number of characters
|
||||||
|
that can still be inserted before the string reaches its
|
||||||
|
capacity.
|
||||||
|
|
||||||
|
@par Complexity
|
||||||
|
|
||||||
|
Constant.
|
||||||
|
*/
|
||||||
|
BOOST_STATIC_STRING_CPP11_CONSTEXPR
|
||||||
|
size_type
|
||||||
|
available() const noexcept
|
||||||
|
{
|
||||||
|
return max_size() - size();
|
||||||
|
}
|
||||||
|
|
||||||
/** Increase the capacity.
|
/** Increase the capacity.
|
||||||
|
|
||||||
This function has no effect.
|
This function has no effect.
|
||||||
|
|||||||
@@ -72,9 +72,8 @@ struct cxper_char_traits
|
|||||||
// This implementation does not handle overlapping ranges where
|
// This implementation does not handle overlapping ranges where
|
||||||
// dest > src. A correct implementation would need to detect this
|
// dest > src. A correct implementation would need to detect this
|
||||||
// case and copy backwards, but detecting overlap requires pointer
|
// case and copy backwards, but detecting overlap requires pointer
|
||||||
// comparisons that are not allowed in constant expressions when
|
// comparisons that many of the tested compilers (incorrectly) refuse
|
||||||
// the pointers point to unrelated objects (e.g., a string literal
|
// in constant expressions.
|
||||||
// and the static_string's internal buffer).
|
|
||||||
//
|
//
|
||||||
// Since cxper_char_traits is only used for testing constexpr
|
// Since cxper_char_traits is only used for testing constexpr
|
||||||
// functionality and the tests do not exercise overlapping moves
|
// functionality and the tests do not exercise overlapping moves
|
||||||
|
|||||||
@@ -989,6 +989,29 @@ testCapacity()
|
|||||||
BOOST_TEST(static_string<3>{"abc"}.max_size() == 3);
|
BOOST_TEST(static_string<3>{"abc"}.max_size() == 3);
|
||||||
BOOST_TEST(static_string<5>{"abc"}.max_size() == 5);
|
BOOST_TEST(static_string<5>{"abc"}.max_size() == 5);
|
||||||
|
|
||||||
|
// available()
|
||||||
|
BOOST_TEST(static_string<0>{}.available() == 0);
|
||||||
|
BOOST_TEST(static_string<1>{}.available() == 1);
|
||||||
|
BOOST_TEST(static_string<1>{"a"}.available() == 0);
|
||||||
|
BOOST_TEST(static_string<3>{"abc"}.available() == 0);
|
||||||
|
BOOST_TEST(static_string<5>{"abc"}.available() == 2);
|
||||||
|
BOOST_TEST(static_string<5>{}.available() == 5);
|
||||||
|
{
|
||||||
|
static_string<8> s("hi");
|
||||||
|
BOOST_TEST(s.available() == 6);
|
||||||
|
s.append(" there");
|
||||||
|
BOOST_TEST(s.available() == 0);
|
||||||
|
s.clear();
|
||||||
|
BOOST_TEST(s.available() == 8);
|
||||||
|
}
|
||||||
|
// Intended use with the pos/count-taking overloads.
|
||||||
|
{
|
||||||
|
static_string<5> s("ab");
|
||||||
|
s.append(string_view{"xyzwv"}, 0, s.available());
|
||||||
|
BOOST_TEST(s == "abxyz");
|
||||||
|
BOOST_TEST(s.available() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
// reserve(std::size_t n)
|
// reserve(std::size_t n)
|
||||||
static_string<3>{}.reserve(0);
|
static_string<3>{}.reserve(0);
|
||||||
static_string<3>{}.reserve(1);
|
static_string<3>{}.reserve(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user