Compare commits

..

73 Commits

Author SHA1 Message Date
Gennaro Prota
e9313dc331 Add an experimental basic_static_cstring template in example/
This introduces an alternative to basic_static_string designed for use
in POD types: Trivially copyable, having a sizeof == N + 1, with no
embedded NULs.

Placed in example/ to gather user feedback before committing to a public
API. See issue #23.
2025-12-19 19:32:30 +01:00
Gennaro Prota
0c5e5b8e58 Fix our deduction guide 2025-12-19 18:26:40 +01:00
Gennaro Prota
6f0c00b268 Work around a Clang 3.7 bug affecting constexpr insert()
The iterator-based insert(const_iterator, size_type, value_type)
function relies on traits_type::move() to shift the existing null
terminator to its new position. Clang 3.7's constexpr evaluator does not
handle this correctly, causing the following test to fail:

  static_string<3>{"ab"}.insert(2, 1, 'c') == "abc"

Add an explicit term() call, guarded by a preprocessor conditional for
Clang 3.7, to ensure proper null termination.
2025-12-19 18:23:33 +01:00
Gennaro Prota
2175496c55 Condition the NTTP tests on __cpp_nontype_template_args
They were conditioned on detection of C++20 via __cplusplus, but Clang
10 and 11 don't support class types as NTTP, even though they report
C++20 via __cplusplus when -std=c++20 is used.
2025-12-19 18:23:33 +01:00
Gennaro Prota
aee3c62957 Apply the workaround in the previous commit to Clang 3.7 and 9-19, too
Reason: They have the same issue as GCC 9.
2025-12-19 18:23:33 +01:00
Gennaro Prota
0e28b358dc Work around GCC 9 rejecting a legitimate pointer comparison in a constexpr context 2025-12-19 18:23:33 +01:00
Gennaro Prota
4dcfb39494 Replace the implementation of cxper_char_traits::move() with a simpler one
Reason: See the new code comment.
2025-12-19 18:23:33 +01:00
Gennaro Prota
4bf6461ca1 Work around a bug in GCC 5-10
GCC 5-10 incorrectly complain about our nested classes being private.
So, make them public.
2025-12-19 18:23:33 +01:00
Krystian Stasiowski
67efdf6a9b Make basic_static_string usable as a NTTP 2025-12-19 18:23:33 +01:00
Krystian Stasiowski
3a410b8472 Add build directory and CMake preset files to .gitignore 2025-12-19 18:23:33 +01:00
Gennaro Prota
bf988466f8 Work around GCC (libstdc++) bug #113200
See the previous commit. This simple fix avoids calling Traits::move(),
which is where the bug resides.

This closes issue #55.
2025-12-16 10:30:33 +01:00
Gennaro Prota
a526ebd1f6 Check that basic_static_string can be constructed and assigned from a C-style string in a constexpr context
This triggers a libstdc++ issue which was fixed in GCC 12.4 and 13.3:
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113200>. If our CI shows
we bump into that bug, we'll add a workaround.
2025-12-16 10:30:33 +01:00
Gennaro Prota
2f8c7a69ea Update the library metadata: Remove Krystian, add myself as a maintainer 2025-12-15 14:25:26 +01:00
Gennaro Prota
c915934529 Fix four occorrences of a typo ("arugment") in the Javadoc comments 2025-11-14 12:03:00 +01:00
Gennaro Prota
10b5491104 Avoid two C4244 warnings from MSVC 2025-11-05 11:30:41 +01:00
Alexander Grund
a58319dbdd Switch boost.io to boost.org 2025-10-24 11:59:10 +02:00
Alexander Grund
4c84b61975 README: Replace travis badges by GHA badges 2025-10-24 11:59:10 +02:00
Alexander Grund
fbd6051165 Update Link to regression test matrix in README 2025-10-24 11:59:10 +02:00
Alexander Grund
db1ea76a17 Fix required CMake version
`source_group(TREE` requires CMake 3.8
2025-10-24 11:58:47 +02:00
Alexander Grund
ee172b86fd Try standalone only with >=C++17 2025-10-24 11:57:55 +02:00
Alexander Grund
bd3dd01259 Update Drone from Boost.CI 2025-10-24 11:57:55 +02:00
Gennaro Prota
a841869405 Remove a use of std::strcpy() to avoid a C4996 warning from MSVC 2025-10-24 11:00:21 +02:00
Alexander Grund
3613e9578d Fix standalone build with Clang
The config.hpp uses `BOOST_LIBSTDCXX_VERSION` which isn't defined in
standalone mode so `BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW` will
be defined.
This then causes build failures for code expecting the availability of
string_view.
2025-10-24 10:11:37 +02:00
Alexander Grund
6f17b60377 Guard test requiring string_view 2025-10-24 10:11:37 +02:00
Gennaro Prota
815678e1e7 CI: Test C++26/2c again 2025-10-23 16:49:48 +02:00
Gennaro Prota
2cc22bf5a8 Align to_static_[w]string() with C++26 std::to_[w]string()
C++26 specifies that std::to_string() and std::to_wstring() format
floating point values as if using std::format(). This commit updates the
internal conversion helpers to match that behavior, using
std::format_to_n() for efficient, allocation-free formatting directly
into the static_string/static_wstring buffer.

Fallbacks using snprintf()/swprintf() remain active for pre-C++26
builds.

This ensures consistent formatting across standard and Boost APIs.
2025-10-23 16:49:48 +02:00
Gennaro Prota
d6f976a7df Fix the sizes of the strings returned by to_static_string() and to_static_wstring() for floating point values 2025-10-23 16:49:48 +02:00
Gennaro Prota
7b564d8d26 Fix two macro names in the unit tests 2025-10-22 19:18:39 +02:00
Gennaro Prota
3c37deed99 Fix the previous commit 2025-10-22 19:11:09 +02:00
Gennaro Prota
34ef5c45be Remove an unused dependency on Boost.StaticAssert
This closes issue #73.
2025-10-22 19:06:12 +02:00
Kenneth Reitz
0f34644488 Update libraries.json /s/container/containers
The other libraries reference "containers" instead of "container"
2025-10-22 18:48:18 +02:00
Dmitry Arkhipov
4c27826548 use Python version of Docca 2025-10-22 18:35:38 +02:00
Gennaro Prota
9c5d69475d Implement the arithmetic conversions in terms of resize_and_overwrite()
Reason: Performing the conversions without accessing private members,
providing a model for users to implement their own with comparable
efficiency.
2025-10-09 17:45:16 +02:00
Gennaro Prota
300781d954 Add a resize_and_overwrite() member
Reason: This is in preparation of the next commit. See its commit
message.
2025-10-09 17:45:16 +02:00
Gennaro Prota
cd1a1a41c3 Don't use an additional buffer in the arithmetic conversions
In the case of the floating point conversions, this effectively avoids a
copy of the buffer contents. In the case of the integer conversions, it
doesn't eliminate the copy, but still removes the extra buffer.

This fixes issue #65.
2025-10-09 17:45:16 +02:00
Alexander Grund
0d255f7438 Appveyor: Update MinGW 32bit job
Use the variant from Boost.CI

Fixes #68
2025-10-07 10:19:31 +02:00
Alexander Grund
17d77ef5bb Disable multi-arch CI job 2025-10-06 17:22:47 +02:00
Alexander Grund
20afd07676 Pass char arrays instead of static_string instances to testR
Avoid stack overflow in MSVC caused by huge amount of static_string instances

Fixes #70
2025-10-06 17:22:47 +02:00
Alexander Grund
7f903ef7ce Add cxx11_hdr_type_traits B2 requirement
Avoid failures with GCC < 5
2025-10-06 17:22:47 +02:00
Alexander Grund
5dfbb1f2b1 CI: Disable coverage and coverity jobs 2025-10-06 17:22:47 +02:00
Arthur O'Dwyer
37a557d937 Make static_string trivially copyable 2025-10-03 18:42:10 +02:00
Alexander Grund
cd546285c4 CI: Don't test C++26/2c 2025-10-03 12:12:05 +02:00
Alexander Grund
645bf0a27d Simplify testTS
Replace boolean by check for defaulted nullptr
2025-10-03 12:12:05 +02:00
Alexander Grund
5067dfce5f Use BOOST_TEST_EQ for to_static_string tests using floating point values 2025-10-03 12:12:05 +02:00
Alexander Grund
d37197d773 Add CMake subdir test for CI 2025-10-03 12:12:05 +02:00
Alexander Grund
a421cf742c Switch to reusable GHA workflow
Avoid the current failures due to outdated CI configs
2025-10-03 12:12:05 +02:00
Rene Rivera
7a53b7ff20 Move include to target. 2025-05-02 19:21:11 +03:00
Rene Rivera
24d62635a3 Put back whitespace. 2025-05-02 19:21:11 +03:00
Rene Rivera
a8f671ea1e Attempt to fix GHA. 2025-05-02 19:21:11 +03:00
Rene Rivera
d677c9436c Update build deps. 2025-05-02 19:21:11 +03:00
Rene Rivera
a3cc7bcf95 Move inter-lib dependencies to a project variable and into the build targets. 2025-05-02 19:21:11 +03:00
Rene Rivera
70578731e7 Update copyright dates. 2025-05-02 19:21:11 +03:00
Rene Rivera
3fb22ed769 Bump B2 require to 5.2 2025-05-02 19:21:11 +03:00
Rene Rivera
32824bfa1d Add requires-b2 check to top-level build file. 2025-05-02 19:21:11 +03:00
Rene Rivera
f15a4d0586 Add missing import-search for cconfig/predef checks. 2025-05-02 19:21:11 +03:00
Rene Rivera
cd5bc51e9e Replace relative docca refs with project based. 2025-05-02 19:21:11 +03:00
Rene Rivera
77d6a43dce Switch to library requirements instead of source. As source puts extra source in install targets. 2025-05-02 19:21:11 +03:00
Rene Rivera
8f969a62f7 Make the library modular usable. 2025-05-02 19:21:11 +03:00
alandefreitas
bff5cb65a5 Boost super-project tests target
fix #53
2024-02-20 13:53:27 -03:00
Krystian Stasiowski
42bb99ed25 support platforms without wchar_t
closes #51
2023-10-24 14:22:30 -04:00
Krystian Stasiowski
175f467a03 select hash implementation with macros based on word size
fixes #46
2023-05-29 11:30:18 -04:00
Krystian Stasiowski
6275cd7fe3 disable string_view overloads when type is convertible to basic_static_string
fixes #47
2023-05-29 10:51:06 -04:00
alandefreitas
ac84c4f40e string_view interoperability
fix #26
2023-01-19 19:57:32 -03:00
alandefreitas
269987446e check for char8_t directly
fix #40
2023-01-18 22:10:36 -03:00
alandefreitas
82ff4e0679 static_string<0> does not memcpy
fix #41
2023-01-18 22:09:45 -03:00
alandefreitas
9c3d5febe7 tests include main header 2023-01-18 22:09:31 -03:00
alandefreitas
0c914ff05b fix noexcept-type warning 2022-11-04 10:34:09 -07:00
alandefreitas
bfce6eea90 fix unused-function warning 2022-11-03 22:48:35 -07:00
alandefreitas
ffce33d483 fix array-bounds warning 2022-11-03 14:12:02 -07:00
alandefreitas
c4f6491537 fix restrict warning 2022-11-02 15:46:33 -07:00
alandefreitas
25579e482f update jamfile
fix #24
2022-11-01 14:11:31 -07:00
alandefreitas
3e9489a7af update CMakeLists.txt
fix #4
2022-11-01 13:39:05 -07:00
sdarwin
7822f1b991 update CI
fix #31, fix #20
2022-10-31 16:09:33 -07:00
31 changed files with 4406 additions and 2091 deletions

View File

@@ -1,5 +1,6 @@
# Copyright 2016, 2017 Peter Dimov
# Copyright (C) 2017 - 2019 James E. King III
# Copyright 2017 - 2019 James E. King III
# Copyright 2019 - 2021 Alexander Grund
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@@ -21,7 +22,7 @@
version: 1.0.{build}-{branch}
shallow_clone: true
shallow_clone: false
branches:
only:
@@ -33,115 +34,101 @@ branches:
- /pr\/.*/
matrix:
fast_finish: false
# Adding MAYFAIL to any matrix job allows it to fail but the build stays green:
allow_failures:
- MAYFAIL: true
environment:
global:
B2_CI_VERSION: 1
GIT_FETCH_JOBS: 4
# see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties
# to use the default for a given environment, comment it out; recommend you build debug and release however:
# on Windows it is important to exercise all the possibilities, especially shared vs static, however most
# libraries that care about this exercise it in their Jamfiles...
# B2_ADDRESS_MODEL: address-model=64,32
# B2_LINK: link=shared,static
B2_ADDRESS_MODEL: 32,64
B2_LINK: shared,static
# B2_THREADING: threading=multi,single
B2_VARIANT: variant=release
B2_VARIANT: release
matrix:
- FLAVOR: Visual Studio 2022
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 14,17,20
B2_TOOLSET: msvc-14.3
- FLAVOR: Visual Studio 2019
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
B2_ADDRESS_MODEL: address-model=64
B2_CXXFLAGS: cxxflags=-permissive-
B2_CXXSTD: 17 # 2a
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 14,17,2a
B2_TOOLSET: msvc-14.2
- FLAVOR: Visual Studio 2017 C++2a Strict
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_ADDRESS_MODEL: address-model=64
B2_CXXFLAGS: cxxflags=-permissive-
B2_CXXSTD: 17 # 2a
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 2a
B2_TOOLSET: msvc-14.1
- FLAVOR: Visual Studio 2017 C++17
- FLAVOR: Visual Studio 2017 C++14/17
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_ADDRESS_MODEL: address-model=64
B2_CXXSTD: 17
B2_TOOLSET: msvc-14.1
B2_VARIANT: variant=debug
- FLAVOR: Visual Studio 2017 C++14 (Default)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_ADDRESS_MODEL: address-model=64,32
B2_CXXSTD: 14,17
B2_TOOLSET: msvc-14.1
- FLAVOR: clang-cl
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_ADDRESS_MODEL: address-model=64
B2_CXXSTD: 11
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDCOMMANDS: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"'
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 11,14,17
B2_TOOLSET: clang-win
- FLAVOR: Visual Studio 2015 C++14 (Default)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_ADDRESS_MODEL: address-model=64,32
B2_TOOLSET: msvc-14.0
B2_VARIANT: variant=debug
# not supported
# - FLAVOR: Visual Studio 2015, 2013
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
# B2_TOOLSET: msvc-12.0,msvc-14.0
- FLAVOR: Visual Studio 2010, 2012, 2013
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0
# - FLAVOR: Visual Studio 2008, 2010, 2012
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
# B2_TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
# B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: cygwin (32-bit)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: address-model=32
B2_CXXSTD: 03,11
# https://github.com/boostorg/test/issues/144
B2_DEFINES: define=_POSIX_C_SOURCE=200112L
B2_THREADING: threadapi=pthread
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 11,14,1z
B2_TOOLSET: gcc
B2_VARIANT: variant=debug
- FLAVOR: cygwin (64-bit)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: address-model=64
B2_CXXSTD: 11,17
# https://github.com/boostorg/test/issues/144
B2_DEFINES: define=_POSIX_C_SOURCE=200112L define=__USE_ISOC99
B2_THREADING: threadapi=pthread
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 11,14,1z
B2_TOOLSET: gcc
- FLAVOR: mingw32
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ARCH: i686
B2_ADDRESS_MODEL: address-model=32
B2_CXXSTD: 03,11
SCRIPT: ci\appveyor\mingw.bat
B2_VARIANT: variant=debug
- FLAVOR: mingw64 (32-bit)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 11,14,17,2a
B2_TOOLSET: gcc
- FLAVOR: mingw64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ARCH: x86_64
B2_ADDRESS_MODEL: address-model=64
B2_CXXSTD: 11,17
B2_DEFINES: define=__USE_ISOC99
SCRIPT: ci\appveyor\mingw.bat
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 11,14,17,2a
B2_TOOLSET: gcc
install:
- set SELF=%APPVEYOR_PROJECT_NAME:-=_%
- git clone https://github.com/boostorg/boost-ci.git C:\boost-ci
- xcopy /s /e /q /i C:\boost-ci\ci .\ci
- '%ADDCOMMANDS%'
- git clone --depth 1 https://github.com/boostorg/boost-ci.git C:\boost-ci-cloned
# Copy ci folder if not testing Boost.CI
- if NOT "%APPVEYOR_PROJECT_NAME%" == "boost-ci" xcopy /s /e /q /i /y C:\boost-ci-cloned\ci .\ci
- rmdir /s /q C:\boost-ci-cloned
- ci\appveyor\install.bat
build: off
test_script:
- set SELF=%APPVEYOR_PROJECT_NAME:-=_%
- PATH=%ADDPATH%%PATH%
# The definition of B2_TOOLCXX omits B2_CXXSTD= if it was not defined above
- IF NOT DEFINED B2_CXXSTD (SET B2_TOOLCXX=toolset=%B2_TOOLSET%) ELSE (SET B2_TOOLCXX=toolset=%B2_TOOLSET% cxxstd=%B2_CXXSTD%)
# Echo the complete build command to the build log
- IF NOT DEFINED SCRIPT (ECHO b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3)
# Now go build...
- IF DEFINED SCRIPT (call libs\%SELF%\%SCRIPT%) ELSE (b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3)
test_script: ci\build.bat

View File

@@ -1,276 +0,0 @@
# Copyright 2015-2019 Rene Rivera.
# Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#
# Generic Azure Pipelines build script for boostorg repositories
# See: https://github.com/boostorg/boost-ci/
#
# Instructions for customizing this script for your library:
#
# 1. Customize the compilers and language levels you want.
# 2. If you have more than include/, src/, test/, example/, examples/,
# benchmark/ or tools/ directories, set the environment variable DEPINST.
# For example if your build uses code in "bench/" and "fog/" directories:
# - DEPINST: --include bench --include fog
# 3. Enable pull request builds in your boostorg/<library> account.
#
# That's it - the script will do everything else for you.
trigger:
branches:
include:
- develop
- master
- bugfix/*
- feature/*
- fix/*
- pr/*
pr:
branches:
include:
- develop
variables:
- name: B2_VARIANT
value: variant=release,debug
stages:
- stage: Test
jobs:
- job: 'Linux'
pool:
vmImage: 'ubuntu-16.04'
strategy:
matrix:
GCC 8:
B2_TOOLSET: gcc
B2_CXXSTD: 14,17
CXX: g++-8
PACKAGES: g++-8
GCC 7:
B2_TOOLSET: gcc
B2_CXXSTD: 11,14,17
CXX: g++-7
PACKAGES: g++-7
GCC 6:
B2_TOOLSET: gcc
B2_CXXSTD: 11,14
CXX: g++-6
PACKAGES: g++-6
GCC 5:
B2_TOOLSET: gcc
B2_CXXSTD: 11
CXX: g++-5
PACKAGES: g++-5
GCC 4.9:
B2_TOOLSET: gcc
B2_CXXSTD: 11
CXX: g++-4.9
PACKAGES: g++-4.9
GCC 4.8:
B2_TOOLSET: gcc
B2_CXXSTD: 11
CXX: g++-4.8
PACKAGES: g++-4.8
Clang 8:
B2_TOOLSET: clang
B2_CXXSTD: 14,17
CXX: clang++-8
PACKAGES: clang-8
LLVM_REPO: llvm-toolchain-xenial-8
Clang 7:
B2_TOOLSET: clang
B2_CXXSTD: 14,17
CXX: clang++-7
PACKAGES: clang-7
LLVM_REPO: llvm-toolchain-xenial-7
Clang 6:
B2_TOOLSET: clang
B2_CXXSTD: 14,17
CXX: clang++-6.0
PACKAGES: clang-6.0
LLVM_REPO: llvm-toolchain-xenial-6.0
Clang 5:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17
PACKAGES: clang-5.0
CXX: clang++-5.0
LLVM_REPO: llvm-toolchain-xenial-5.0
Clang 4:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17
CXX: clang++-4.0
PACKAGES: clang-4.0
LLVM_REPO: llvm-toolchain-xenial-4.0
Clang 3.9:
B2_TOOLSET: clang
B2_CXXSTD: 11,14
CXX: clang++-3.9
PACKAGES: clang-3.9
Clang 3.8:
B2_TOOLSET: clang
CXX: clang++-3.8
B2_CXXSTD: 11,14
PACKAGES: clang-3.8
Clang 3.7:
B2_TOOLSET: clang
B2_CXXSTD: 11
CXX: clang++-3.7
PACKAGES: clang-3.7
Clang 3.6:
B2_TOOLSET: clang
B2_CXXSTD: 11
CXX: clang++-3.6
PACKAGES: clang-3.6
Clang 3.5:
B2_TOOLSET: clang
B2_CXXSTD: 11
CXX: clang++-3.5
PACKAGES: clang-3.5
steps:
- bash: |
set -e
uname -a
sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
if test -n "${LLVM_REPO}" ; then
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo -E apt-add-repository "deb http://apt.llvm.org/xenial/ ${LLVM_REPO} main"
fi
sudo -E apt-get update
sudo -E apt-get -yq --no-install-suggests --no-install-recommends install ${PACKAGES}
git clone --branch master https://github.com/boostorg/boost-ci.git boost-ci
cp -pr boost-ci/ci boost-ci/.codecov.yml .
rm -rf boost-ci
source ci/azure-pipelines/install.sh
# AzP requires to run special task in order to export
# SELF and BOOST_ROOT as job-scoped variable from a script.
# NOTE: Disable set -x is necessary, see the troubleshooting guide
# on "Variables having ' (single quote) appended":
# https://docs.microsoft.com/en-us/azure/devops/pipelines/troubleshooting
set +x
echo "##vso[task.setvariable variable=SELF]"$SELF
echo "##vso[task.setvariable variable=BOOST_ROOT]"$BOOST_ROOT
set -x
displayName: 'Install'
- bash: |
set -e
echo "SELF=$SELF"
echo "BOOST_ROOT=$BOOST_ROOT"
cd $BOOST_ROOT/libs/$SELF
ci/azure-pipelines/build.sh --debug-configuration
displayName: 'Build'
- job: 'Windows'
strategy:
matrix:
VS 2019 C++17 Strict:
B2_TOOLSET: msvc-14.2
B2_CXXSTD: 17
B2_CXXFLAGS: cxxflags=-permissive-
B2_ADDRESS_MODEL: address-model=64
VM_IMAGE: 'windows-2019'
VS 2017 C++17 Strict:
B2_TOOLSET: msvc-14.1
B2_CXXSTD: 17
B2_CXXFLAGS: cxxflags=-permissive-
B2_ADDRESS_MODEL: address-model=64
VM_IMAGE: 'vs2017-win2016'
VS 2017 C++17:
B2_TOOLSET: msvc-14.1
B2_CXXSTD: 17
B2_ADDRESS_MODEL: address-model=64,32
VM_IMAGE: 'vs2017-win2016'
VS 2017 C++14:
B2_TOOLSET: msvc-14.1
#B2_CXXSTD: 14 # default
B2_ADDRESS_MODEL: address-model=64,32
VM_IMAGE: 'vs2017-win2016'
pool:
vmImage: $(VM_IMAGE)
steps:
- script: |
set SELF=%BUILD_REPOSITORY_NAME:-=_%
for /f "tokens=2 delims=/" %%a in ("%SELF%") do set SELF=%%a
set BOOST_ROOT=%BUILD_SOURCESDIRECTORY%\boost-root
git clone --branch master https://github.com/boostorg/boost-ci.git boost-ci
xcopy /s /e /q /i boost-ci\ci .\ci
cmd /k ci\azure-pipelines\install.bat
echo ##vso[task.setvariable variable=SELF]%SELF%
echo ##vso[task.setvariable variable=BOOST_ROOT]%BOOST_ROOT%
displayName: 'Install'
- script: |
PATH=%ADDPATH%%PATH%
REM The definition of B2_TOOLCXX omits B2_CXXSTD= if it was not defined above
IF NOT DEFINED B2_CXXSTD (SET B2_TOOLCXX=toolset=%B2_TOOLSET%) ELSE (SET B2_TOOLCXX=toolset=%B2_TOOLSET% cxxstd=%B2_CXXSTD%)
cd %BOOST_ROOT%
ECHO b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3
b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3
displayName: 'Build'
- job: 'macOS'
pool:
vmImage: 'macOS-10.14'
strategy:
matrix:
Xcode_11_3_1:
B2_TOOLSET: clang
B2_CXXSTD: 14,17,2a
XCODE_APP: /Applications/Xcode_11.3.1.app
Xcode_11_2_1:
B2_TOOLSET: clang
B2_CXXSTD: 14,17,2a
XCODE_APP: /Applications/Xcode_11.2.1.app
Xcode_11_2:
B2_TOOLSET: clang
B2_CXXSTD: 14,17,2a
XCODE_APP: /Applications/Xcode_11.2.app
Xcode_11_1:
B2_TOOLSET: clang
B2_CXXSTD: 14,17,2a
XCODE_APP: /Applications/Xcode_11.1.app
Xcode_10_3:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17,2a
XCODE_APP: /Applications/Xcode_10.3.app
Xcode_10_2_1:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17,2a
XCODE_APP: /Applications/Xcode_10.2.1.app
Xcode_10_2:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17,2a
XCODE_APP: /Applications/Xcode_10.2.app
Xcode_10_1:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17,2a
XCODE_APP: /Applications/Xcode_10.1.app
Xcode_10_0:
B2_TOOLSET: clang
B2_CXXSTD: 11,14,17,2a
XCODE_APP: /Applications/Xcode_10.app
steps:
- bash: |
set -e
git clone --branch master https://github.com/boostorg/boost-ci.git boost-ci-cloned
cp -prf boost-ci-cloned/ci .
rm -rf boost-ci-cloned
source ci/azure-pipelines/install.sh
displayName: Install
- bash: |
set -e
echo "SELF=$SELF"
echo "BOOST_ROOT=$BOOST_ROOT"
cd $BOOST_ROOT/libs/$SELF
ci/azure-pipelines/build.sh
displayName: 'Build'

25
.codecov.yml Normal file
View File

@@ -0,0 +1,25 @@
# Copyright 2019 - 2021 Alexander Grund
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#
# Sample codecov configuration file. Edit as required
codecov:
max_report_age: off
require_ci_to_pass: yes
notify:
# Increase this if you have multiple coverage collection jobs
after_n_builds: 1
wait_for_ci: yes
# Change how pull request comments look
comment:
layout: "reach,diff,flags,files,footer"
# Ignore specific files or folders. Glob patterns are supported.
# See https://docs.codecov.com/docs/ignoring-paths
ignore:
- extra/*
- extra/**/*
- test/*
- test/**/*

117
.drone.star Normal file
View File

@@ -0,0 +1,117 @@
# Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE.txt)
#
# Copyright (c) 2020 Rene Rivera
# Copyright (c) 2022 Alan de Freitas
# Copyright (c) 2022-2025 Alexander Grund
# For Drone CI we use the Starlark scripting language to reduce duplication.
# As the yaml syntax for Drone CI is rather limited.
# Base environment for all jobs
globalenv={'B2_VARIANT': 'release'}
# Wrapper function to apply the globalenv to all jobs
def job(
# job specific environment options
env={},
**kwargs):
real_env = dict(globalenv)
real_env.update(env)
return job_impl(env=real_env, **kwargs)
def main(ctx):
return [
job(compiler='clang-3.8', cxxstd='11,14', os='ubuntu-16.04'),
job(compiler='clang-3.9', cxxstd='11,14', os='ubuntu-18.04'),
job(compiler='clang-4.0', cxxstd='11,14', os='ubuntu-18.04'),
job(compiler='clang-5.0', cxxstd='11,14,1z', os='ubuntu-18.04'),
job(compiler='clang-6.0', cxxstd='11,14,17', os='ubuntu-18.04'),
job(compiler='clang-7', cxxstd='11,14,17', os='ubuntu-18.04'),
job(compiler='clang-8', cxxstd='11,14,17,2a', os='ubuntu-18.04'),
job(compiler='clang-9', cxxstd='11,14,17,2a', os='ubuntu-18.04'),
job(compiler='clang-10', cxxstd='11,14,17,2a', os='ubuntu-18.04'),
job(compiler='clang-11', cxxstd='11,14,17,2a', os='ubuntu-22.04'),
job(compiler='clang-12', cxxstd='11,14,17,20', os='ubuntu-22.04'),
job(compiler='clang-13', cxxstd='11,14,17,20,2b', os='ubuntu-22.04'),
job(compiler='clang-14', cxxstd='11,14,17,20,2b', os='ubuntu-22.04'),
job(compiler='clang-15', cxxstd='11,14,17,20,2b', os='ubuntu-22.04', add_llvm=True,
env={'B2_CXXFLAGS': '-Werror'}),
job(name='Clang 15 standalone', compiler='clang-15', cxxstd='17,20,2b', os='ubuntu-22.04', add_llvm=True,
env={'B2_CXXFLAGS': '-Werror', 'B2_DEFINES': 'BOOST_STATIC_STRING_STANDALONE'}),
job(compiler='gcc-4.8', cxxstd='11', os='ubuntu-16.04'),
job(compiler='gcc-4.9', cxxstd='11', os='ubuntu-16.04'),
job(compiler='gcc-5', cxxstd='11,14,1z', os='ubuntu-18.04'),
job(compiler='gcc-6', cxxstd='11,14,1z', os='ubuntu-18.04'),
job(compiler='gcc-7', cxxstd='11,14,1z', os='ubuntu-18.04'),
job(compiler='gcc-8', cxxstd='11,14,17,2a', os='ubuntu-18.04'),
job(compiler='gcc-9', cxxstd='11,14,17,2a', os='ubuntu-18.04'),
job(compiler='gcc-10', cxxstd='11,14,17,20', os='ubuntu-22.04'),
job(compiler='gcc-11', cxxstd='11,14,17,20,2b', os='ubuntu-22.04'),
job(compiler='gcc-12', cxxstd='11,14,17,20,2b', os='ubuntu-22.04'),
job(name='Coverage', buildtype='codecov', buildscript='codecov_coveralls', env={'LCOV_BRANCH_COVERAGE': 1, "COVERALLS_REPO_TOKEN": {"from_secret": "coveralls_repo_token"}},
compiler='gcc-8', cxxstd='11,14,17,2a', os='ubuntu-18.04'),
# Sanitizers
job(name='ASAN', asan=True,
compiler='gcc-12', cxxstd='11,14,17,20', os='ubuntu-22.04'),
job(name='UBSAN', ubsan=True,
compiler='gcc-12', cxxstd='11,14,17,20', os='ubuntu-22.04'),
job(name='TSAN', tsan=True,
compiler='gcc-12', cxxstd='11,14,17,20', os='ubuntu-22.04'),
job(name='Clang 14 w/ sanitizers', asan=True, ubsan=True,
compiler='clang-14', cxxstd='11,14,17,20', os='ubuntu-22.04'),
job(name='Clang 11 libc++ w/ sanitizers', asan=True, ubsan=True, # libc++-11 is the latest working with ASAN: https://github.com/llvm/llvm-project/issues/59432
compiler='clang-11', cxxstd='11,14,17,20', os='ubuntu-20.04', stdlib='libc++', install='libc++-11-dev libc++abi-11-dev'),
job(name='Valgrind', valgrind=True,
compiler='clang-6.0', cxxstd='11,14,1z', os='ubuntu-18.04', install='libc6-dbg libc++-dev libstdc++-8-dev'),
# libc++
job(compiler='clang-6.0', cxxstd='11,14,17,2a', os='ubuntu-18.04', stdlib='libc++', install='libc++-dev libc++abi-dev'),
job(compiler='clang-7', cxxstd='11,14,17,2a', os='ubuntu-20.04', stdlib='libc++', install='libc++-7-dev libc++abi-7-dev'),
job(compiler='clang-8', cxxstd='11,14,17,2a', os='ubuntu-20.04', stdlib='libc++', install='libc++-8-dev libc++abi-8-dev'),
job(compiler='clang-9', cxxstd='11,14,17,2a', os='ubuntu-20.04', stdlib='libc++', install='libc++-9-dev libc++abi-9-dev'),
job(compiler='clang-10', cxxstd='11,14,17,20', os='ubuntu-20.04', stdlib='libc++', install='libc++-10-dev libc++abi-10-dev'),
job(compiler='clang-11', cxxstd='11,14,17,20', os='ubuntu-20.04', stdlib='libc++', install='libc++-11-dev libc++abi-11-dev'),
job(compiler='clang-12', cxxstd='11,14,17,20', os='ubuntu-22.04', stdlib='libc++', install='libc++-12-dev libc++abi-12-dev libunwind-12-dev'),
job(compiler='clang-13', cxxstd='11,14,17,20', os='ubuntu-22.04', stdlib='libc++', install='libc++-13-dev libc++abi-13-dev'),
job(compiler='clang-14', cxxstd='11,14,17,20', os='ubuntu-22.04', stdlib='libc++', install='libc++-14-dev libc++abi-14-dev'),
job(compiler='clang-15', cxxstd='11,14,17,20', os='ubuntu-22.04', stdlib='libc++', install='libc++-15-dev libc++abi-15-dev', add_llvm=True),
# FreeBSD
job(compiler='clang-10', cxxstd='11,14,17,20', os='freebsd-13.1'),
job(compiler='clang-15', cxxstd='11,14,17,20', os='freebsd-13.1'),
job(compiler='gcc-11', cxxstd='11,14,17,20', os='freebsd-13.1', linkflags='-Wl,-rpath=/usr/local/lib/gcc11'),
# OSX
job(compiler='clang', cxxstd='11,14,17,2a', os='osx-xcode-10.1'),
job(compiler='clang', cxxstd='11,14,17,2a', os='osx-xcode-10.3'),
job(compiler='clang', cxxstd='11,14,17,2a', os='osx-xcode-11.1'),
job(compiler='clang', cxxstd='11,14,17,2a', os='osx-xcode-11.7'),
job(compiler='clang', cxxstd='11,14,17,2a', os='osx-xcode-12'),
job(compiler='clang', cxxstd='11,14,17,20', os='osx-xcode-12.5.1'),
job(compiler='clang', cxxstd='11,14,17,20', os='osx-xcode-13.0'),
job(compiler='clang', cxxstd='11,14,17,20', os='osx-xcode-13.4.1'),
job(compiler='clang', cxxstd='11,14,17,20,2b', os='osx-xcode-14.0'),
job(compiler='clang', cxxstd='11,14,17,20,2b', os='osx-xcode-14.3.1'),
job(compiler='clang', cxxstd='11,14,17,20,2b', os='osx-xcode-15.0.1'),
# ARM64
job(compiler='clang-12', cxxstd='11,14,17,20', os='ubuntu-20.04', arch='arm64', add_llvm=True),
job(compiler='gcc-11', cxxstd='11,14,17,20', os='ubuntu-20.04', arch='arm64'),
# S390x
job(compiler='clang-12', cxxstd='11,14,17,20', os='ubuntu-20.04', arch='s390x', add_llvm=True),
job(compiler='gcc-11', cxxstd='11,14,17,20', os='ubuntu-20.04', arch='s390x'),
# Windows
job(compiler='msvc-14.0', cxxstd=None, os='windows', env={'B2_DONT_EMBED_MANIFEST': 1}),
job(compiler='msvc-14.1', cxxstd=None, os='windows'),
job(compiler='msvc-14.2', cxxstd=None, os='windows'),
job(compiler='msvc-14.3', cxxstd=None, os='windows'),
job(compiler='msvc-14.0', cxxstd='14,17,20', os='windows', env={'B2_DONT_EMBED_MANIFEST': 1}),
job(compiler='msvc-14.1', cxxstd='14,17,20', os='windows'),
job(compiler='msvc-14.2', cxxstd='14,17,20', os='windows'),
job(compiler='msvc-14.3', cxxstd='14,17,20,latest', os='windows'),
]
# from https://github.com/boostorg/boost-ci
load("@boost_ci//ci/drone/:functions.star", "linux_cxx", "windows_cxx", "osx_cxx", "freebsd_cxx", "job_impl")

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# Copyright 2020 Rene Rivera, Sam Darwin
# Copyright 2025 Alexander Grund
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt)
set -xe
# Run the regular Boost CI script which does the test & upload to codecov.io
wget https://github.com/boostorg/boost-ci/raw/refs/heads/master/.drone/drone.sh
. drone.sh
# coveralls
# uses multiple lcov steps from boost-ci codecov.sh script
if [ -n "${COVERALLS_REPO_TOKEN}" ]; then
echo "processing coveralls"
pip3 install --user cpp-coveralls
cd "$BOOST_CI_SRC_FOLDER"
export PATH=/tmp/lcov/bin:$PATH
command -v lcov
lcov --version
lcov --remove coverage.info -o coverage_filtered.info '*/test/*' '*/extra/*'
cpp-coveralls --verbose -l coverage_filtered.info
fi

50
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
#
# Copyright 2020-2021 Peter Dimov
# Copyright 2021 Andrey Semashev
# Copyright 2021-2025 Alexander Grund
# Copyright 2022-2025 James E. King III
#
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#
# This workflow uses the Boost.CI reusable workflow which builds a variety of
# configurations of your project, runs tests, and generates code coverage reports.
#
# To use it, copy this file into your repository as `.github/workflows/ci.yml` and
# customize it appropriately.
#
---
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- bugfix/**
- feature/**
- fix/**
- github/**
- pr/**
paths-ignore:
- LICENSE
- meta/**
- README.md
jobs:
call-boost-ci:
name: Run Boost.CI
uses: boostorg/boost-ci/.github/workflows/reusable.yml@master
with:
exclude_cxxstd: '98,03,0x'
enable_pr_coverage: false
enable_multiarch: false
# Example of customization:
# with:
# enable_reflection: true
# enable_windows: false
# secrets:
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}
# COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}

156
.github/workflows/example.yml vendored Normal file
View File

@@ -0,0 +1,156 @@
#
# Copyright (c) 2025 Gennaro Prota (gennaro dot prota at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
#
# Official repository: https://github.com/boostorg/static_string
#
name: Example (basic_static_cstring)
on:
pull_request:
push:
branches:
- master
- develop
- bugfix/**
- feature/**
- fix/**
- github/**
- pr/**
paths-ignore:
- LICENSE
- meta/**
- README.md
jobs:
linux:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- { 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

9
.gitignore vendored
View File

@@ -1,8 +1,15 @@
bin/
bin64/
build/
# Because of CMake and VS2017
Win32/
x64/
.vs/
out/
out/
# VS CMake settings
/CMakeSettings.json
# CMake presets
/CMakePresets.json
/CMakeUserPresets.json

View File

@@ -1,275 +0,0 @@
# Copyright 2016 Peter Dimov
# Copyright 2017 - 2019 James E. King III
# Copyright 2020 Krystian Stasiowski
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#
# Generic Travis CI build script for boostorg repositories
# See: https://github.com/boostorg/boost-ci
#
# Instructions for customizing this script for your library:
#
# 1. Customize the compilers and language levels you want in the 'jobs'.
# 2. If you have more than include/, src/, test/, example/, examples/, or
# tools/ directories, modify your Travis CI project and add the environment
# variable DEPINST. For example if your build uses code in "bench/" and
# "fog/" directories, then set DEPINST to the following:
# --include bench --include fog
# 3. If you want to enable Coverity Scan, you need to provide the environment
# variables COVERITY_SCAN_TOKEN and COVERITY_SCAN_NOTIFICATION_EMAIL in
# your github settings.
# 4. If you want to enable a big-endian build, you need to uncomment the
# big-endian build job.
# 5. Enable pull request builds in your boostorg/<library> account.
#
# That's it - the scripts will do everything else for you.
dist: xenial
language: cpp
env:
global:
# see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties
# - B2_ADDRESS_MODEL=address-model=64,32
# - B2_LINK=link=shared,static
# - B2_THREADING=threading=multi,single
- B2_VARIANT=variant=release
install:
- git clone https://github.com/boostorg/boost-ci.git boost-ci
- cp -pr boost-ci/ci boost-ci/.codecov.yml .
- source ci/travis/install.sh
addons:
apt:
packages:
- binutils-gold
- gdb
- libc6-dbg
- qemu-user-static
services:
- docker
branches:
only:
- master
- develop
- /bugfix\/.*/
- /feature\/.*/
- /fix\/.*/
- /pr\/.*/
script:
- cd $BOOST_ROOT/libs/$SELF
- ci/travis/build.sh
#
# Default toolsets in Ubuntu
#
# trusty xenial bionic
# 14.04 16.04 18.04
# ------ ------ ------
# clang 3.4 3.8 6.0
# gcc 4.8.2 5.3.1 7.3.0
#
anchors:
clang-38: &clang-38 { apt: { packages: [ "clang-3.8",
"libstdc++-6-dev" ], sources: [ "llvm-toolchain-xenial-3.8",
"ubuntu-toolchain-r-test" ] } }
clang-4: &clang-4 { apt: { packages: [ "clang-4.0",
"libstdc++-6-dev" ], sources: [ "llvm-toolchain-xenial-4.0",
"ubuntu-toolchain-r-test" ] } }
clang-5: &clang-5 { apt: { packages: [ "clang-5.0",
"libstdc++-7-dev" ], sources: [ "llvm-toolchain-xenial-5.0",
"ubuntu-toolchain-r-test" ] } }
clang-6: &clang-6 { apt: { packages: [ "clang-6.0",
"libc6-dbg",
"libc++-dev",
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-6.0",
"ubuntu-toolchain-r-test" ] } }
clang-7: &clang-7 { apt: { packages: [ "clang-7",
"libc6-dbg",
"libc++-dev",
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-7",
"ubuntu-toolchain-r-test" ] } }
clang-8: &clang-8 { apt: { packages: [ "clang-8",
"libc6-dbg",
"libc++-dev",
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-8",
"ubuntu-toolchain-r-test" ] } }
gcc-48: &gcc-48 { apt: { packages: [ "g++-4.8" ] } }
gcc-49: &gcc-49 { apt: { packages: [ "g++-4.9" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-5: &gcc-5 { apt: { packages: [ "g++-5" ] } }
gcc-6: &gcc-6 { apt: { packages: [ "g++-6" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-7: &gcc-7 { apt: { packages: [ "g++-7" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-8: &gcc-8 { apt: { packages: [ "g++-8" ], sources: [ "ubuntu-toolchain-r-test" ] } }
gcc-9: &gcc-9 { apt: { packages: [ "g++-9" ], sources: [ "ubuntu-toolchain-r-test" ] } }
jobs:
allow_failures:
- env:
- COPY="all the environment settings from your job"
include:
# coverage
- os: linux
env:
- COMMENT=codecov.io
- B2_CXXSTD=11
- B2_TOOLSET=gcc-8
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
addons: *gcc-8
script:
- cd $BOOST_ROOT/libs/$SELF
- tools/codecov.sh
- os: linux
env:
- COMMENT=asan
- B2_VARIANT=variant=debug
- B2_TOOLSET=gcc-8
- B2_CXXSTD=11,14
- B2_CXXFLAGS="address-sanitizer=norecover"
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
addons: *gcc-8
- os: linux
env:
- COMMENT=tsan
- B2_VARIANT=variant=debug
- B2_TOOLSET=gcc-8
- B2_CXXSTD=11,14
- B2_CXXFLAGS="thread-sanitizer=norecover"
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
addons: *gcc-8
- os: linux
env:
- COMMENT=ubsan
- B2_VARIANT=variant=debug
- B2_TOOLSET=gcc-8
- B2_CXXSTD=11,14
- B2_CXXFLAGS="undefined-sanitizer=norecover"
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
- B2_LINKFLAGS="linkflags=-fuse-ld=gold"
- UBSAN_OPTIONS=print_stacktrace=1
addons: *gcc-8
- os: linux
env:
- COMMENT=valgrind
- B2_TOOLSET=clang-6.0
- B2_CXXSTD=11,14
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
- B2_VARIANT=variant=debug
- B2_TESTFLAGS=testing.launcher=valgrind
- VALGRIND_OPTS=--error-exitcode=1
addons: *clang-6
script:
- cd $BOOST_ROOT/libs/$SELF
- ci/travis/valgrind.sh
# libstdc++
- { os: "linux", dist: "trusty", # xenial has libstdc++ from gcc 5.4.0 with newer ABI
env: [ "B2_TOOLSET=gcc-4.8", "B2_CXXSTD=11" ], addons: *gcc-48 }
- { os: "linux", dist: "trusty", # xenial has libstdc++ from gcc 5.4.0 with newer ABI
env: [ "B2_TOOLSET=gcc-4.9", "B2_CXXSTD=11" ], addons: *gcc-49 }
- { os: "linux", env: [ "B2_TOOLSET=gcc-5", "B2_CXXSTD=11,14" ], addons: *gcc-5 }
- { os: "linux", env: [ "B2_TOOLSET=gcc-6", "B2_CXXSTD=11,14" ], addons: *gcc-6 }
- { os: "linux", env: [ "B2_TOOLSET=gcc-7", "B2_CXXSTD=14,17" ], addons: *gcc-7 }
- { os: "linux", env: [ "B2_TOOLSET=gcc-8", "B2_CXXSTD=17" ], addons: *gcc-8 }
- { os: "linux", env: [ "B2_TOOLSET=gcc-9", "B2_CXXSTD=17" ], addons: *gcc-9 }
- { os: "linux", dist: "trusty", # xenial has libstdc++ from gcc 5.4.0 with newer ABI
env: [ "B2_TOOLSET=clang-3.8", "B2_CXXSTD=11" ], addons: *clang-38 }
- { os: "linux", env: [ "B2_TOOLSET=clang-4.0", "B2_CXXSTD=11,14" ], addons: *clang-4 }
- { os: "linux", env: [ "B2_TOOLSET=clang-5.0", "B2_CXXSTD=11,14" ], addons: *clang-5 }
- { os: "linux", env: [ "B2_TOOLSET=clang-6.0", "B2_CXXSTD=14,17" ], addons: *clang-6 }
- { os: "linux", env: [ "B2_TOOLSET=clang-7", "B2_CXXSTD=17" ], addons: *clang-7 }
- { os: "linux", env: [ "B2_TOOLSET=clang-8", "B2_CXXSTD=17" ], addons: *clang-8 }
- os: "linux"
env: ["B2_TOOLSET=clang-9", "B2_CXXSTD=11,14,17"]
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- clang-9
- libc6-dbg
- libc++-dev
- libstdc++-8-dev
# libc++
- { os: "linux", env: [ "B2_TOOLSET=clang-6.0", "B2_CXXSTD=11,14",
"B2_CXXFLAGS=-stdlib=libc++" ], addons: *clang-6 }
- { os: "osx" , env: [ "B2_TOOLSET=clang", "B2_CXXSTD=11,17" ] }
# to enable Intel ICC define INTEL_ICC_SERIAL_NUMBER and the following (under development):
# - { os: "linux", env: [ "B2_TOOLSET=intel-linux", "B2_CXXSTD=11,14,17" ], addons: *gcc-7,
# script: cd $BOOST_ROOT/libs/$SELF && ci/travis/intelicc.sh }
# uncomment to enable a big-endian build job, just note that it is 5-10 times slower
# than a regular build and travis has a 50 minute time limit per job
# - os: linux
# env:
# - COMMENT=big-endian
# - B2_CXXSTD=03
# - B2_TOOLSET=gcc
# - B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
# - BDDE_OS=red
# - BDDE_ARCH=ppc64
# script:
# - cd $BOOST_ROOT/libs/$SELF
# - ci/travis/bdde.sh
# - os: linux
# env:
# - COMMENT=cppcheck
# script:
# - cd $BOOST_ROOT/libs/$SELF
# - ci/travis/cppcheck.sh
#################### Jobs to run on pushes to master, develop ###################
# Coverity Scan
- os: linux
if: (env(COVERITY_SCAN_NOTIFICATION_EMAIL) IS present) AND (branch IN (develop, master)) AND (type IN (cron, push))
env:
- COMMENT="Coverity Scan"
- B2_TOOLSET=clang
script:
- cd $BOOST_ROOT/libs/$SELF
- ci/travis/coverity.sh
# Standalone tests for StaticString
- { os: "linux", env: [ "COMMENT=STANDALONE", "B2_TOOLSET=gcc-7", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ], addons: *gcc-7 }
- { os: "linux", env: [ "COMMENT=STANDALONE", "B2_TOOLSET=gcc-8", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ], addons: *gcc-8 }
- { os: "linux", env: [ "COMMENT=STANDALONE", "B2_TOOLSET=gcc-9", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ], addons: *gcc-9 }
- { os: "linux", env: [ "COMMENT=STANDALONE", "B2_TOOLSET=clang-6.0", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ], addons: *clang-6 }
- { os: "linux", env: [ "COMMENT=STANDALONE", "B2_TOOLSET=clang-7", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ], addons: *clang-7 }
- { os: "linux", env: [ "COMMENT=STANDALONE", "B2_TOOLSET=clang-8", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ], addons: *clang-8 }
- os: "linux"
env: ["COMMENT=STANDALONE", "B2_TOOLSET=clang-9", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17"]
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- clang-9
- libc6-dbg
- libc++-dev
- libstdc++-8-dev
- { os: "osx" , env: [ "COMMENT=STANDALONE", "B2_TOOLSET=clang", "B2_DEFINES=define=BOOST_STATIC_STRING_STANDALONE", "B2_CXXSTD=17" ] }
notifications:
email:
false

View File

@@ -1,32 +1,5 @@
# Generated by `boostdep --cmake static_string`
# Copyright 2020 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.5...3.16)
project(boost_static_string VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
add_library(boost_static_string INTERFACE)
add_library(Boost::static_string ALIAS boost_static_string)
target_include_directories(boost_static_string INTERFACE include)
target_link_libraries(boost_static_string
INTERFACE
Boost::assert
Boost::container_hash
Boost::static_assert
Boost::throw_exception
Boost::utility
)
else()
#
# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
# Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -34,140 +7,111 @@ else()
# Official repository: https://github.com/boostorg/static_string
#
#-------------------------------------------------------------------------------
cmake_minimum_required(VERSION 3.8...3.16)
function (DoGroupSources curdir rootdir folder)
file (GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
foreach (child ${children})
if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
DoGroupSources (${curdir}/${child} ${rootdir} ${folder})
elseif (${child} STREQUAL "CMakeLists.txt")
source_group("" FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
else()
string (REGEX REPLACE ^${rootdir} ${folder} groupname ${curdir})
string (REPLACE "/" "\\" groupname ${groupname})
source_group (${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
endforeach()
endfunction()
project(boost_static_string VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
function (GroupSources curdir folder)
DoGroupSources (${curdir} ${curdir} ${folder})
endfunction()
set(BOOST_STATIC_STRING_IS_ROOT OFF)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(BOOST_STATIC_STRING_IS_ROOT ON)
endif ()
#-------------------------------------------------------------------------------
#
# StaticString
#
#-------------------------------------------------------------------------------
if (BOOST_STATIC_STRING_IS_ROOT)
include(CTest)
endif ()
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
# Options
if (NOT BOOST_SUPERPROJECT_VERSION)
option(BOOST_STATIC_STRING_INSTALL "Install boost::static_string files" ${BOOST_STATIC_STRING_IS_ROOT})
option(BOOST_STATIC_STRING_BUILD_TESTS "Build boost::static_string tests" OFF)
else ()
set(BOOST_STATIC_STRING_BUILD_TESTS ${BUILD_TESTING})
endif ()
if (MSVC)
set (CMAKE_VERBOSE_MAKEFILE FALSE)
# Find boost
if (BOOST_SUPERPROJECT_VERSION)
set(BOOST_STATIC_STRING_FIND_PACKAGE_BOOST OFF)
elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../CMakeLists.txt" AND
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../Jamroot" AND
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../boost-build.jam" AND
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../bootstrap.sh" AND
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../libs")
set(BOOST_STATIC_STRING_FIND_PACKAGE_BOOST OFF)
else ()
set(BOOST_STATIC_STRING_FIND_PACKAGE_BOOST ON)
endif ()
add_definitions (
-D_WIN32_WINNT=0x0601
)
if (BOOST_STATIC_STRING_FIND_PACKAGE_BOOST)
find_package(Boost 1.78.0 REQUIRED COMPONENTS container)
elseif (BOOST_STATIC_STRING_IS_ROOT)
set(BOOST_STATIC_STRING_UNIT_TEST_LIBRARIES core)
set(BOOST_INCLUDE_LIBRARIES static_string assert container_hash throw_exception utility ${BOOST_STATIC_STRING_UNIT_TEST_LIBRARIES})
set(BOOST_EXCLUDE_LIBRARIES static_string)
set(CMAKE_FOLDER Dependencies)
add_subdirectory(../.. Dependencies/boost EXCLUDE_FROM_ALL)
unset(CMAKE_FOLDER)
endif ()
add_compile_options(
/permissive- # strict C++
/W4 # enable all warnings
/MP # Multi-processor compilation
# Sources
include(GNUInstallDirs)
file(GLOB_RECURSE BOOST_STATIC_STRING_HEADERS CONFIGURE_DEPENDS
include/boost/*.hpp
include/boost/*.ipp
include/boost/*.natvis
)
set (Boost_USE_STATIC_LIBS ON)
set (Boost_USE_STATIC_RUNTIME ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/include/boost PREFIX "" FILES ${BOOST_STATIC_STRING_HEADERS})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/src PREFIX "" FILES ${BOOST_STATIC_STRING_SOURCES})
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ob2 /Oi /Ot /GL /MT")
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi /Ot /MT")
# Target
add_library(boost_static_string INTERFACE)
add_library(Boost::static_string ALIAS boost_static_string)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
target_compile_features(boost_static_string INTERFACE cxx_constexpr)
if (BOOST_SUPERPROJECT_VERSION)
target_include_directories(boost_static_string INTERFACE "${PROJECT_SOURCE_DIR}/include")
else ()
target_include_directories(boost_static_string
INTERFACE
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
endif ()
# for RelWithDebInfo builds, disable incremental linking
# since CMake sets it ON by default for that build type and it
# causes warnings
#
string (REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" replacement_flags
${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO})
set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacement_flags})
if (BOOST_STATIC_STRING_FIND_PACKAGE_BOOST)
target_link_libraries(boost_static_string
INTERFACE
Boost::headers
)
else ()
target_link_libraries(boost_static_string
INTERFACE
Boost::assert
Boost::container_hash
Boost::core
Boost::throw_exception
Boost::utility
)
endif ()
else()
set (THREADS_PREFER_PTHREAD_FLAG ON)
find_package (Threads)
if (BOOST_STATIC_STRING_INSTALL AND NOT BOOST_SUPERPROJECT_VERSION)
install(TARGETS boost_static_string
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
set( CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wpedantic -Wno-unused-parameter")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/boost
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN "*.hpp"
PATTERN "*.ipp"
)
endif ()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wrange-loop-analysis")
endif ()
endif()
# Must come before Boost includes, otherwise the
# IDE sees the wrong file due to boost/ symlinks.
include_directories (include)
if (BUILD_TESTING OR BOOST_STATIC_STRING_BUILD_TESTS)
add_subdirectory(test)
endif ()
#-------------------------------------------------------------------------------
#
# Boost
#
#-------------------------------------------------------------------------------
get_filename_component (BOOST_ROOT ../../ ABSOLUTE)
# VFALCO I want static but "b2 stage" builds a minimal set which excludes static
add_definitions (-DBOOST_ALL_STATIC_LINK=1)
include_directories (${BOOST_ROOT})
link_directories(${BOOST_ROOT}/stage/lib)
#-------------------------------------------------------------------------------
if ("${VARIANT}" STREQUAL "coverage")
if (MSVC)
else()
set (CMAKE_BUILD_TYPE DEBUG)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 --coverage")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
endif()
elseif ("${VARIANT}" STREQUAL "ubasan")
if (MSVC)
else()
set (CMAKE_BUILD_TYPE RELWITHDEBINFO)
set (CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -msse4.2 -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fno-sanitize-recover=address,undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/tools/blacklist.supp")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined -fno-sanitize-recover=address,undefined")
endif()
elseif ("${VARIANT}" STREQUAL "debug")
set (CMAKE_BUILD_TYPE DEBUG)
elseif ("${VARIANT}" STREQUAL "release")
set (CMAKE_BUILD_TYPE RELEASE)
endif()
#-------------------------------------------------------------------------------
#GroupSources (test "/")
#-------------------------------------------------------------------------------
#
# Tests and examples
#
#include_directories (.)
file (GLOB_RECURSE PROJECT_FILES
${PROJECT_SOURCE_DIR}/include/boost/static_string/*.hpp
${PROJECT_SOURCE_DIR}/include/boost/static_string/*.ipp
)
add_subdirectory (test)
endif()

10
Jamfile
View File

@@ -1,10 +0,0 @@
#
# Copyright (c) 2019 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Official repository: https://github.com/boostorg/static_string
#
build-project test ;

View File

@@ -1,9 +1,9 @@
# Boost.StaticString
Branch | Travis | Appveyor | Azure Pipelines | codecov.io | Docs | Matrix |
Branch | GHA CI | Appveyor | Azure Pipelines | codecov.io | Docs | Matrix |
:-------------: | ------ | -------- | --------------- | ---------- | ---- | ------ |
[`master`](https://github.com/boostorg/static_string/tree/master) | [![Build Status](https://travis-ci.org/boostorg/static_string.svg?branch=master)](https://travis-ci.org/boostorg/static_string) | [![Build status](https://ci.appveyor.com/api/projects/status/64es4wg4w7mc5wn2/branch/master?svg=true)](https://ci.appveyor.com/project/sdkrystian/static-string/branch/master) | [![Build Status](https://krystiands.visualstudio.com/static_string/_apis/build/status/Boost.StaticString?branchName=master)](https://krystiands.visualstudio.com/static_string/_build/latest?definitionId=3&branchName=master) | [![codecov](https://codecov.io/gh/boostorg/static_string/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/static_string/branch/master) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/static_string) | [![Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/static_string.html)
[`develop`](https://github.com/boostorg/static_string/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/static_string.svg?branch=develop)](https://travis-ci.org/boostorg/static_string) | [![Build status](https://ci.appveyor.com/api/projects/status/64es4wg4w7mc5wn2/branch/develop?svg=true)](https://ci.appveyor.com/project/sdkrystian/static-string/branch/develop) | [![Build Status](https://krystiands.visualstudio.com/static_string/_apis/build/status/Boost.StaticString?branchName=develop)](https://krystiands.visualstudio.com/static_string/_build/latest?definitionId=3&branchName=develop) | [![codecov](https://codecov.io/gh/boostorg/static_string/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/static_string/branch/develop) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/libs/static_string) | [![Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/static_string.html)
[`master`](https://github.com/boostorg/static_string/tree/master) | [![Build Status](https://github.com/boostorg/static_string/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/static_string/actions?query=branch:master) | [![Build status](https://ci.appveyor.com/api/projects/status/64es4wg4w7mc5wn2/branch/master?svg=true)](https://ci.appveyor.com/project/sdkrystian/static-string/branch/master) | [![Build Status](https://krystiands.visualstudio.com/static_string/_apis/build/status/Boost.StaticString?branchName=master)](https://krystiands.visualstudio.com/static_string/_build/latest?definitionId=3&branchName=master) | [![codecov](https://codecov.io/gh/boostorg/static_string/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/static_string/branch/master) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/release/libs/static_string) | [![Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](https://regression.boost.org/master/developer/static_string.html)
[`develop`](https://github.com/boostorg/static_string/tree/develop) | [![Build Status](https://github.com/boostorg/static_string/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/static_string/actions?query=branch:develop) | [![Build status](https://ci.appveyor.com/api/projects/status/64es4wg4w7mc5wn2/branch/develop?svg=true)](https://ci.appveyor.com/project/sdkrystian/static-string/branch/develop) | [![Build Status](https://krystiands.visualstudio.com/static_string/_apis/build/status/Boost.StaticString?branchName=develop)](https://krystiands.visualstudio.com/static_string/_build/latest?definitionId=3&branchName=develop) | [![codecov](https://codecov.io/gh/boostorg/static_string/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/static_string/branch/develop) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/libs/static_string) | [![Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](https://regression.boost.org/develop/developer/static_string.html)
## Introduction

27
build.jam Normal file
View File

@@ -0,0 +1,27 @@
# Copyright René Ferdinand Rivera Morell 2023-2024
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
require-b2 5.2 ;
constant boost_dependencies :
/boost/assert//boost_assert
/boost/config//boost_config
/boost/container_hash//boost_container_hash
/boost/core//boost_core
/boost/throw_exception//boost_throw_exception
/boost/utility//boost_utility ;
project /boost/static_string
;
explicit
[ alias boost_static_string : : :
: <include>include <library>$(boost_dependencies) ]
[ alias all : boost_static_string test ]
;
call-if : boost-library static_string
;

View File

@@ -1,6 +1,7 @@
#
# Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
# Copyright (c) 2020 Krystian Stasiowski (sdkrystian at gmail dot com)
# Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -8,20 +9,21 @@
project static_string/doc ;
import boostbook ;
import ../../../tools/docca/docca.jam ;
import-search /boost/docca ;
import docca ;
import path ;
import os ;
docca.reference reference.qbk
local include-prefix = [ path.root $(__file__:D) [ path.pwd ] ] ;
include-prefix = [ path.native $(include-prefix:D)/include ] ;
docca.pyreference reference.qbk
:
xsl/custom-overrides.xsl
[ glob-tree-ex ../include/boost/static_string : *.hpp *.ipp : detail impl ]
externals.hpp
:
<doxygen:param>PROJECT_NAME=StaticString
<doxygen:param>PROJECT_BRIEF="String Library"
<doxygen:param>ALIASES="esafe=\"@par Exception Safety\""
<doxygen:param>FILE_PATTERNS=
<doxygen:param>EXAMPLE_PATTERNS=
<doxygen:param>DISTRIBUTE_GROUP_DOC=YES
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>EXPAND_ONLY_PREDEF=YES
@@ -38,19 +40,17 @@ docca.reference reference.qbk
<doxygen:param>EXTRACT_ALL=YES
<doxygen:param>EXTRACT_PRIVATE=YES
<doxygen:param>EXTRACT_LOCAL_CLASSES=NO
<doxygen:param>SHOW_INCLUDE_FILES=NO
<doxygen:param>INLINE_INFO=NO
<doxygen:param>SORT_MEMBER_DOCS=NO
<doxygen:param>SORT_MEMBERS_CTORS_1ST=YES
<doxygen:param>SHOW_USED_FILES=NO
<doxygen:param>SHOW_FILES=NO
<doxygen:param>SHOW_NAMESPACES=NO
<doxygen:param>CLASS_DIAGRAMS=NO
<doxygen:param>STRIP_FROM_PATH=$(include-prefix)
# <doxygen:param>ALLOW_UNICODE_NAMES=NO
# <doxygen:param>GROUP_NESTED_COMPOUNDS=NO
# <doxygen:param>HIDE_COMPOUND_REFERENCE=NO
# <doxygen:param>WARN_AS_ERROR=NO
<docca:config>config.json
;
#-------------------------------------------------------------------------------
@@ -90,7 +90,7 @@ boostbook static_string
<xsl:param>chapter.autolabel=0
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
<xsl:param>generate.toc=""
<xsl:param>generate.toc="chapter toc,title section nop reference nop"
<include>../../../tools/boostbook/dtd
:
<dependency>images

12
doc/config.json Normal file
View File

@@ -0,0 +1,12 @@
{
"include_private": false,
"legacy_behavior": false,
"external_marker": "!EXTERNAL!",
"link_prefix": "static_string.ref.",
"default_namespace": "boost::static_strings",
"allowed_prefixes": ["boost::static_strings::", "std::"],
"convenience_header": "boost/static_string.hpp",
"replace_strings": {
"__see_below__": "``['see-below]``"
}
}

64
doc/externals.hpp Normal file
View File

@@ -0,0 +1,64 @@
#pragma once
namespace boost {
/// !EXTERNAL!
///
/// @see https://www.boost.org/doc/libs/release/libs/utility/doc/html/utility/utilities/string_view.html
template <class T, class Traits>
struct basic_string_view {};
} // namespace boost
namespace std {
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/iterator/reverse_iterator
template <class T>
struct reverse_iterator {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/types/size_t
struct size_t {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/types/integer
struct uint64_t {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/types/integer
struct int64_t {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/types/nullptr_t
struct nullptr_t {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/types/ptrdiff_t
struct ptrdiff_t {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/utility/initializer_list
template <class T>
struct initializer_list {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/io/basic_ostream
template <class T, class Traits>
struct basic_ostream {};
/// !EXTERNAL!
///
/// @see https://en.cppreference.com/w/cpp/types/numeric_limits
template <class T>
struct numeric_limits {};
} // namespace std

View File

@@ -1,11 +0,0 @@
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
expand-text="yes">
<xsl:variable name="doc-ref" select="'static_string.ref'"/>
<xsl:variable name="doc-ns" select="'boost::static_strings'"/>
<xsl:variable name="include-private-members" select="false()"/>
</xsl:stylesheet>

View File

@@ -0,0 +1,19 @@
#
# Copyright (c) 2025 Gennaro Prota (gennaro dot prota at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
#
# Official repository: https://github.com/boostorg/static_string
#
import testing ;
project
: requirements
<include>../../include
<warnings>extra
<cxxstd>20
;
run static_cstring_test.cpp ;

View File

@@ -0,0 +1,13 @@
This directory contains an experimental implementation of `basic_static_cstring`, which differs from `basic_static_string` in the following ways:
| | `basic_static_cstring` | `basic_static_string` |
|---------------------|------------------------|-----------------------|
| Layout | `sizeof == N + 1` | Has size member |
| Embedded NULs | Not supported | Supported |
| Trivially copyable | Yes | No |
Additionally, when `N <= UCHAR_MAX`, `basic_static_cstring` employs an optimization that avoids calling `std::strlen()` to compute the size.
This work stems from [boostorg/static_string#23](https://github.com/boostorg/static_string/issues/23).
If you believe `basic_static_cstring` should become part of the public API, please share your feedback on the Boost mailing list.

View File

@@ -0,0 +1,441 @@
//
// Copyright (c) 2025 Gennaro Prota (gennaro dot prota at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/static_string
//
#ifndef BOOST_STATIC_STRING_STATIC_CSTRING_HPP
#define BOOST_STATIC_STRING_STATIC_CSTRING_HPP
#include <boost/static_string/config.hpp>
#include <algorithm>
#include <climits>
#include <cstddef>
#include <ostream>
#include <string>
#include <string_view>
#include <stdexcept>
#include <type_traits>
namespace boost {
namespace static_strings {
namespace detail {
// Primary template: No remaining-capacity trick; uses traits::length() for length.
template<std::size_t N, typename CharT, typename Traits, bool UseRemaining>
class static_cstring_base
{
public:
using traits_type = Traits;
using value_type = CharT;
using size_type = std::size_t;
value_type data_[N + 1]{};
constexpr size_type get_size() const noexcept
{
return traits_type::length(data_);
}
constexpr void set_size(size_type sz) noexcept
{
data_[sz] = 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: Uses remaining-capacity trick.
template<std::size_t N, typename CharT, typename Traits>
class static_cstring_base<N, CharT, Traits, true>
{
public:
using traits_type = Traits;
using value_type = CharT;
using size_type = std::size_t;
value_type data_[N + 1]{};
constexpr size_type get_size() const noexcept
{
return N - static_cast<unsigned char>(data_[N]);
}
constexpr void set_size(size_type sz) noexcept
{
data_[sz] = value_type{};
data_[N] = static_cast<value_type>(N - sz);
}
// 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
template<std::size_t N, typename CharT = char, typename Traits = std::char_traits<CharT>>
class basic_static_cstring
: public detail::static_cstring_base<N, CharT, Traits, (N <= UCHAR_MAX)>
{
public:
using base = detail::static_cstring_base<N, CharT, Traits, (N <= UCHAR_MAX)>;
using base::data_;
using base::get_size;
using base::set_size;
// Member types
using traits_type = Traits;
using value_type = CharT;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using iterator = pointer;
using const_iterator = const_pointer;
static constexpr size_type npos = static_cast<size_type>(-1);
static constexpr size_type static_capacity = N;
// Constructors.
constexpr basic_static_cstring() noexcept
{
set_size(0);
}
constexpr basic_static_cstring(const CharT* s)
{
assign(s);
}
constexpr basic_static_cstring(const CharT* s, size_type count)
{
assign(s, count);
}
constexpr basic_static_cstring(size_type count, CharT ch)
{
assign(count, ch);
}
template<std::size_t M>
constexpr basic_static_cstring(const CharT (&arr)[M])
{
static_assert(M <= N + 1, "String literal too long for static_cstring");
assign(arr, M - 1);
}
constexpr size_type size() const noexcept
{
return get_size();
}
constexpr size_type length() const noexcept
{
return size();
}
constexpr bool empty() const noexcept
{
return data_[0] == value_type{};
}
static constexpr size_type max_size() noexcept
{
return N;
}
static constexpr size_type capacity() noexcept
{
return N;
}
// Element access.
constexpr reference operator[](size_type pos) noexcept
{
return data_[pos];
}
constexpr const_reference operator[](size_type pos) const noexcept
{
return data_[pos];
}
constexpr reference at(size_type pos)
{
if (pos >= size())
{
throw std::out_of_range("static_cstring::at");
}
return data_[pos];
}
constexpr const_reference at(size_type pos) const
{
if (pos >= size())
{
throw std::out_of_range("static_cstring::at");
}
return data_[pos];
}
constexpr reference front() noexcept
{
BOOST_STATIC_STRING_ASSERT(!empty());
return data_[0];
}
constexpr const_reference front() const noexcept
{
BOOST_STATIC_STRING_ASSERT(!empty());
return data_[0];
}
constexpr reference back() noexcept
{
BOOST_STATIC_STRING_ASSERT(!empty());
return data_[size() - 1];
}
constexpr const_reference back() const noexcept
{
BOOST_STATIC_STRING_ASSERT(!empty());
return data_[size() - 1];
}
constexpr pointer data() noexcept
{
return data_;
}
constexpr const_pointer data() const noexcept
{
return data_;
}
constexpr const_pointer c_str() const noexcept
{
return data_;
}
// Iterators.
constexpr iterator begin() noexcept
{
return data_;
}
constexpr const_iterator begin() const noexcept
{
return data_;
}
constexpr const_iterator cbegin() const noexcept
{
return data_;
}
constexpr iterator end() noexcept
{
return data_ + size();
}
constexpr const_iterator end() const noexcept
{
return data_ + size();
}
constexpr const_iterator cend() const noexcept
{
return data_ + size();
}
// Modifiers.
constexpr void clear() noexcept
{
set_size(0);
}
constexpr basic_static_cstring& assign(const CharT* s)
{
return assign(s, traits_type::length(s));
}
constexpr basic_static_cstring& assign(const CharT* s, size_type count)
{
if (count > N)
{
throw std::length_error("static_cstring::assign");
}
traits_type::copy(data_, s, count);
set_size(count);
return *this;
}
constexpr basic_static_cstring& assign(size_type count, CharT ch)
{
if (count > N)
{
throw std::length_error("static_cstring::assign");
}
traits_type::assign(data_, count, ch);
set_size(count);
return *this;
}
constexpr basic_static_cstring& operator=(const CharT* s)
{
return assign(s);
}
constexpr void push_back(CharT ch)
{
const size_type sz = size();
if (sz >= N)
{
throw std::length_error("static_cstring::push_back");
}
data_[sz] = ch;
set_size(sz + 1);
}
constexpr void pop_back() noexcept
{
BOOST_STATIC_STRING_ASSERT(!empty());
set_size(size() - 1);
}
constexpr basic_static_cstring& append(const CharT* s)
{
return append(s, traits_type::length(s));
}
constexpr basic_static_cstring& append(const CharT* s, size_type count)
{
const size_type sz = size();
if (sz + count > N)
{
throw std::length_error("static_cstring::append");
}
traits_type::copy(data_ + sz, s, count);
set_size(sz + count);
return *this;
}
constexpr basic_static_cstring& append(size_type count, CharT ch)
{
const size_type sz = size();
if (sz + count > N)
{
throw std::length_error("static_cstring::append");
}
traits_type::assign(data_ + sz, count, ch);
set_size(sz + count);
return *this;
}
constexpr basic_static_cstring& operator+=(const CharT* s)
{
return append(s);
}
constexpr basic_static_cstring& operator+=(CharT ch)
{
push_back(ch);
return *this;
}
// Comparisons.
constexpr int compare(const basic_static_cstring& other) const noexcept
{
const size_type lhs_sz = size();
const size_type rhs_sz = other.size();
const int result = traits_type::compare(data_, other.data_, (std::min)(lhs_sz, rhs_sz));
return result != 0
? result
: lhs_sz < rhs_sz
? -1
: lhs_sz > rhs_sz
? 1
: 0;
}
constexpr int compare(const CharT* s) const noexcept
{
return compare(basic_static_cstring(s));
}
// Conversions.
constexpr operator std::basic_string_view<CharT, Traits>() const noexcept
{
return {data_, size()};
}
std::basic_string<CharT, Traits> str() const
{
return {data_, size()};
}
// Swap.
constexpr void swap(basic_static_cstring& other) noexcept
{
basic_static_cstring tmp = *this;
*this = other;
other = tmp;
}
// Defaulted comparisons for structural type (C++20).
constexpr bool operator==(const basic_static_cstring&) const noexcept = default;
constexpr auto operator<=>(const basic_static_cstring&) const noexcept = default;
};
#if defined(BOOST_STATIC_STRING_USE_DEDUCT)
// Deduction guide.
template<std::size_t N, typename CharT>
basic_static_cstring(const CharT(&)[N]) -> basic_static_cstring<N - 1, CharT>;
#endif
// Comparison with const CharT*.
template<std::size_t N, typename CharT, typename Traits>
constexpr bool operator==(const basic_static_cstring<N, CharT, Traits>& lhs,
const CharT* rhs) noexcept
{
return lhs.compare(rhs) == 0;
}
template<std::size_t N, typename CharT, typename Traits>
constexpr bool operator==(const CharT* lhs,
const basic_static_cstring<N, CharT, Traits>& rhs) noexcept
{
return rhs.compare(lhs) == 0;
}
// Stream output.
template<std::size_t N, typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
const basic_static_cstring<N, CharT, Traits>& str)
{
return os << str.c_str();
}
// Alias templates.
template<std::size_t N>
using static_cstring = basic_static_cstring<N, char>;
template<std::size_t N>
using static_wcstring = basic_static_cstring<N, wchar_t>;
}
}
#endif

View File

@@ -0,0 +1,671 @@
//
// Copyright (c) 2025 Gennaro Prota (gennaro dot prota at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/static_string
//
#include "static_cstring.hpp"
#include <boost/core/lightweight_test.hpp>
#include <climits>
#include <cstring>
#include <sstream>
#include <string>
#include <string_view>
#include <type_traits>
namespace boost {
namespace static_strings {
static
void
testCStringSizeGuarantee()
{
// Core guarantee: sizeof is exactly N + 1 (no size member).
static_assert(sizeof(static_cstring<0>) == 1, "");
static_assert(sizeof(static_cstring<1>) == 2, "");
static_assert(sizeof(static_cstring<10>) == 11, "");
static_assert(sizeof(static_cstring<63>) == 64, "");
static_assert(sizeof(static_cstring<64>) == 65, "");
static_assert(sizeof(static_cstring<127>) == 128, "");
static_assert(sizeof(static_cstring<UCHAR_MAX>) == (UCHAR_MAX + 1), "");
static_assert(sizeof(static_cstring<UCHAR_MAX + 1>) == (UCHAR_MAX + 2), "");
static_assert(sizeof(static_cstring<1000>) == 1001, "");
}
static
void
testCStringRemainingCapacityTrick()
{
// Test the remaining-capacity optimization for N <= UCHAR_MAX.
// Full capacity: Last byte is both null terminator AND remaining == 0.
{
static_cstring<5> full("12345");
BOOST_TEST(full.size() == 5);
BOOST_TEST(full.capacity() == 5);
BOOST_TEST(full.data()[5] == '\0');
BOOST_TEST(std::strcmp(full.c_str(), "12345") == 0);
}
// Partial fill: Null terminator at position size, remaining at position N.
{
static_cstring<10> partial("Hi");
BOOST_TEST(partial.size() == 2);
BOOST_TEST(partial.capacity() == 10);
BOOST_TEST(partial.data()[2] == '\0');
BOOST_TEST(static_cast<unsigned char>(partial.data()[10]) == 8);
}
// Empty string.
{
static_cstring<10> empty;
BOOST_TEST(empty.size() == 0);
BOOST_TEST(empty.capacity() == 10);
BOOST_TEST(empty.data()[0] == '\0');
BOOST_TEST(static_cast<unsigned char>(empty.data()[10]) == 10);
}
// Edge case: N == UCHAR_MAX (max for our trick).
{
static_cstring<UCHAR_MAX> large;
large.assign(100, 'x');
BOOST_TEST(large.size() == 100);
BOOST_TEST(large.capacity() == UCHAR_MAX);
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
void
testCStringTypeTraits()
{
{
using S = static_cstring<0>;
CStringTypeTraits< S > check;
static_cast<void>(check);
}
{
using S = static_cstring<63>;
CStringTypeTraits< S > check;
static_cast<void>(check);
}
{
using S = static_cstring<300>;
CStringTypeTraits< S > check;
static_cast<void>(check);
}
}
static
void
testCStringConstruct()
{
// Default construction.
{
static_cstring<1> s;
BOOST_TEST(s.empty());
BOOST_TEST(s.size() == 0);
BOOST_TEST(s == "");
BOOST_TEST(*s.end() == 0);
}
// Construct with count and char.
{
static_cstring<4> s1(3, 'x');
BOOST_TEST(!s1.empty());
BOOST_TEST(s1.size() == 3);
BOOST_TEST(s1 == "xxx");
BOOST_TEST(*s1.end() == 0);
BOOST_TEST_THROWS(
(static_cstring<2>(3, 'x')),
std::length_error);
}
// Construct from a C string.
{
static_cstring<5> s1("12345");
BOOST_TEST(s1.size() == 5);
BOOST_TEST(s1 == "12345");
BOOST_TEST(*s1.end() == 0);
BOOST_TEST_THROWS(
(static_cstring<4>("12345")),
std::length_error);
}
// Construct from a C string with count.
{
static_cstring<5> s1("UVXYZ", 3);
BOOST_TEST(s1 == "UVX");
BOOST_TEST(*s1.end() == 0);
}
// Copy construction.
{
static_cstring<5> s1("12345");
static_cstring<5> s2(s1);
BOOST_TEST(s2 == "12345");
BOOST_TEST(*s2.end() == 0);
}
}
static
void
testCStringAssignment()
{
// assign(size_type count, CharT ch).
BOOST_TEST(static_cstring<3>{}.assign(1, '*') == "*");
BOOST_TEST(static_cstring<3>{}.assign(3, '*') == "***");
BOOST_TEST(static_cstring<3>{"abc"}.assign(3, '*') == "***");
BOOST_TEST_THROWS(static_cstring<1>{"a"}.assign(2, '*'), std::length_error);
// assign(CharT const* s, size_type count).
BOOST_TEST(static_cstring<3>{}.assign("abc", 3) == "abc");
BOOST_TEST(static_cstring<3>{"*"}.assign("abc", 3) == "abc");
BOOST_TEST_THROWS(static_cstring<1>{}.assign("abc", 3), std::length_error);
// assign(CharT const* s).
BOOST_TEST(static_cstring<3>{}.assign("abc") == "abc");
BOOST_TEST(static_cstring<3>{"*"}.assign("abc") == "abc");
BOOST_TEST_THROWS(static_cstring<1>{}.assign("abc"), std::length_error);
// operator=(const CharT* s).
{
static_cstring<3> s1;
s1 = "123";
BOOST_TEST(s1 == "123");
BOOST_TEST(*s1.end() == 0);
static_cstring<1> s2;
BOOST_TEST_THROWS(
s2 = "123",
std::length_error);
}
// Copy assignment.
{
static_cstring<3> s1("123");
static_cstring<3> s2;
s2 = s1;
BOOST_TEST(s2 == "123");
BOOST_TEST(*s2.end() == 0);
}
}
static
void
testCStringElements()
{
using ccs3 = static_cstring<3> const;
// at(size_type pos).
BOOST_TEST(static_cstring<3>{"abc"}.at(0) == 'a');
BOOST_TEST(static_cstring<3>{"abc"}.at(2) == 'c');
BOOST_TEST_THROWS(static_cstring<3>{""}.at(0), std::out_of_range);
BOOST_TEST_THROWS(static_cstring<3>{"abc"}.at(4), std::out_of_range);
// at(size_type pos) const.
BOOST_TEST(ccs3{"abc"}.at(0) == 'a');
BOOST_TEST(ccs3{"abc"}.at(2) == 'c');
BOOST_TEST_THROWS(ccs3{""}.at(0), std::out_of_range);
// operator[](size_type pos).
BOOST_TEST(static_cstring<3>{"abc"}[0] == 'a');
BOOST_TEST(static_cstring<3>{"abc"}[2] == 'c');
BOOST_TEST(static_cstring<3>{"abc"}[3] == 0);
BOOST_TEST(static_cstring<3>{""}[0] == 0);
// front() / back().
BOOST_TEST(static_cstring<3>{"abc"}.front() == 'a');
BOOST_TEST(static_cstring<3>{"abc"}.back() == 'c');
// data() / c_str().
{
static_cstring<3> s("123");
BOOST_TEST(std::memcmp(s.data(), "123", 3) == 0);
BOOST_TEST(std::memcmp(s.c_str(), "123\0", 4) == 0);
}
// Modification through element access.
{
static_cstring<5> s("12345");
s[1] = '_';
BOOST_TEST(s == "1_345");
s.front() = 'A';
BOOST_TEST(s == "A_345");
s.back() = 'Z';
BOOST_TEST(s == "A_34Z");
}
}
static
void
testCStringIterators()
{
{
static_cstring<3> s;
BOOST_TEST(std::distance(s.begin(), s.end()) == 0);
s = "123";
BOOST_TEST(std::distance(s.begin(), s.end()) == 3);
}
{
static_cstring<3> const s("123");
BOOST_TEST(std::distance(s.begin(), s.end()) == 3);
BOOST_TEST(std::distance(s.cbegin(), s.cend()) == 3);
}
// Iteration.
{
static_cstring<5> s("hello");
std::string result;
for (const char c : s)
{
result += c;
}
BOOST_TEST(result == "hello");
}
}
static
void
testCStringCapacity()
{
// empty().
BOOST_TEST(static_cstring<0>{}.empty());
BOOST_TEST(static_cstring<1>{}.empty());
BOOST_TEST(!static_cstring<1>{"a"}.empty());
// size().
BOOST_TEST(static_cstring<0>{}.size() == 0);
BOOST_TEST(static_cstring<1>{"a"}.size() == 1);
BOOST_TEST(static_cstring<5>{"abc"}.size() == 3);
// length().
BOOST_TEST(static_cstring<0>{}.length() == 0);
BOOST_TEST(static_cstring<3>{"abc"}.length() == 3);
// max_size().
BOOST_TEST(static_cstring<0>{}.max_size() == 0);
BOOST_TEST(static_cstring<5>{"abc"}.max_size() == 5);
// capacity().
BOOST_TEST(static_cstring<0>{}.capacity() == 0);
BOOST_TEST(static_cstring<5>{"abc"}.capacity() == 5);
}
static
void
testCStringClear()
{
static_cstring<3> s("123");
BOOST_TEST(!s.empty());
s.clear();
BOOST_TEST(s.empty());
BOOST_TEST(s.size() == 0);
BOOST_TEST(*s.end() == 0);
BOOST_TEST(s == "");
}
static
void
testCStringPushPop()
{
// push_back().
{
static_cstring<5> s("abc");
s.push_back('d');
BOOST_TEST(s == "abcd");
BOOST_TEST(s.size() == 4);
BOOST_TEST(*s.end() == 0);
s.push_back('e');
BOOST_TEST(s == "abcde");
BOOST_TEST(s.size() == 5);
BOOST_TEST_THROWS(s.push_back('f'), std::length_error);
}
// pop_back().
{
static_cstring<5> s("abcde");
s.pop_back();
BOOST_TEST(s == "abcd");
BOOST_TEST(s.size() == 4);
BOOST_TEST(*s.end() == 0);
s.pop_back();
s.pop_back();
s.pop_back();
s.pop_back();
BOOST_TEST(s.empty());
}
}
static
void
testCStringAppend()
{
// append(const CharT* s).
{
static_cstring<12> s("Hello");
s.append(", World");
BOOST_TEST(s == "Hello, World");
BOOST_TEST(*s.end() == 0);
}
{
static_cstring<5> s("abc");
BOOST_TEST_THROWS(s.append("def"), std::length_error);
}
// append(const CharT* s, size_type count)
{
static_cstring<10> s("abc");
s.append("defgh", 3);
BOOST_TEST(s == "abcdef");
BOOST_TEST(*s.end() == 0);
}
// append(size_type count, CharT ch)
{
static_cstring<10> s("abc");
s.append(3, 'x');
BOOST_TEST(s == "abcxxx");
BOOST_TEST(*s.end() == 0);
BOOST_TEST_THROWS(s.append(5, 'y'), std::length_error);
}
// operator+=()
{
static_cstring<10> s("abc");
s += "def";
BOOST_TEST(s == "abcdef");
s += 'g';
BOOST_TEST(s == "abcdefg");
BOOST_TEST(*s.end() == 0);
}
}
static
void
testCStringComparison()
{
// operator==() / operator!=().
{
static_cstring<10> a("abc");
static_cstring<10> b("abc");
static_cstring<10> c("abd");
BOOST_TEST(a == b);
BOOST_TEST(!(a == c));
BOOST_TEST(a != c);
BOOST_TEST(!(a != b));
}
// operator<(), <=(), >(), >=().
{
static_cstring<10> a("abc");
static_cstring<10> b("abd");
BOOST_TEST(a < b);
BOOST_TEST(a <= b);
BOOST_TEST(a <= a);
BOOST_TEST(b > a);
BOOST_TEST(b >= a);
BOOST_TEST(b >= b);
}
// Comparison with CharT const*.
{
static_cstring<10> s("hello");
BOOST_TEST(s == "hello");
BOOST_TEST("hello" == s);
BOOST_TEST(s != "world");
BOOST_TEST("world" != s);
}
// compare().
{
static_cstring<10> s("abc");
BOOST_TEST(s.compare("abc") == 0);
BOOST_TEST(s.compare("abd") < 0);
BOOST_TEST(s.compare("abb") > 0);
}
}
static
void
testCStringConversion()
{
// operator string_view().
{
static_cstring<10> s("hello");
std::string_view sv = s;
BOOST_TEST(sv == "hello");
BOOST_TEST(sv.size() == 5);
}
// str().
{
static_cstring<10> s("hello");
std::string str = s.str();
BOOST_TEST(str == "hello");
BOOST_TEST(str.size() == 5);
}
}
static
void
testCStringStream()
{
static_cstring<10> s("hello");
std::ostringstream oss;
oss << s;
BOOST_TEST(oss.str() == "hello");
}
static
void
testCStringSwap()
{
static_cstring<10> a("hello");
static_cstring<10> b("world");
a.swap(b);
BOOST_TEST(a == "world");
BOOST_TEST(b == "hello");
}
static
void
testCStringConstexpr()
{
// constexpr construction and operations.
constexpr static_cstring<10> ce("test");
static_assert(ce.size() == 4, "");
static_assert(ce[0] == 't', "");
static_assert(ce[1] == 'e', "");
static_assert(ce[2] == 's', "");
static_assert(ce[3] == 't', "");
static_assert(!ce.empty(), "");
static_assert(ce.max_size() == 10, "");
static_assert(ce.capacity() == 10, "");
constexpr static_cstring<5> ce_empty;
static_assert(ce_empty.empty(), "");
static_assert(ce_empty.size() == 0, "");
}
// Helper struct to test NTTP.
template<basic_static_cstring S>
struct NTTPHelper
{
static constexpr std::size_t size() noexcept
{
return S.size();
}
static constexpr const char* c_str() noexcept
{
return S.c_str();
}
};
static
void
testCStringNTTP()
{
// Test non-type template parameter usage (C++20).
// Test size deduction from string literals.
BOOST_TEST(NTTPHelper<"hello">::size() == 5);
BOOST_TEST(NTTPHelper<"">::size() == 0);
BOOST_TEST(NTTPHelper<"test">::size() == 4);
// Test that different strings create different types
constexpr bool same_type = std::is_same_v<
NTTPHelper<"hello">,
NTTPHelper<"hello">>;
BOOST_TEST(same_type);
constexpr bool different_type = !std::is_same_v<
NTTPHelper<"hello">,
NTTPHelper<"world">>;
BOOST_TEST(different_type);
// Test constexpr access.
constexpr std::size_t len = NTTPHelper<"constexpr">::size();
static_assert(len == 9, "");
}
static
void
testCStringPODUsage()
{
// Test usage in POD types (the original motivation).
struct UserRecord
{
int id;
static_cstring<63> name;
unsigned int flags;
};
static_assert(sizeof(static_cstring<63>) == 64, "");
static_assert(std::is_trivially_copyable<UserRecord>::value, "");
UserRecord user{};
user.id = 42;
user.name = "Alice";
user.flags = 0xFF;
BOOST_TEST(user.id == 42);
BOOST_TEST(user.name.size() == 5);
BOOST_TEST(user.name == "Alice");
BOOST_TEST(user.flags == 0xFF);
// Copy the struct.
UserRecord copy = user;
BOOST_TEST(copy.name == "Alice");
// memcpy() should work.
UserRecord memcpy_dest;
std::memcpy(&memcpy_dest, &user, sizeof(UserRecord));
BOOST_TEST(memcpy_dest.name == "Alice");
}
static
void
testCStringLargeCapacity()
{
// Test strings with N > UCHAR_MAX (no remaining-capacity trick).
{
static_cstring<300> s;
BOOST_TEST(s.empty());
BOOST_TEST(s.size() == 0);
s = "This is a test string";
BOOST_TEST(s.size() == 21);
BOOST_TEST(s == "This is a test string");
s.clear();
BOOST_TEST(s.empty());
}
// Large string operations.
{
static_cstring<500> s;
s.assign(400, 'x');
BOOST_TEST(s.size() == 400);
BOOST_TEST(s[0] == 'x');
BOOST_TEST(s[399] == 'x');
BOOST_TEST(*s.end() == 0);
}
}
static
void
testCStringWideChar()
{
// Test with wchar_t.
{
static_wcstring<10> ws;
BOOST_TEST(ws.empty());
BOOST_TEST(ws.size() == 0);
}
{
static_wcstring<10> ws(L"hello");
BOOST_TEST(ws.size() == 5);
BOOST_TEST(ws[0] == L'h');
BOOST_TEST(ws[4] == L'o');
BOOST_TEST(*ws.end() == 0);
}
}
int
runTests()
{
testCStringSizeGuarantee();
testCStringRemainingCapacityTrick();
testCStringTypeTraits();
testCStringConstruct();
testCStringAssignment();
testCStringElements();
testCStringIterators();
testCStringCapacity();
testCStringClear();
testCStringPushPop();
testCStringAppend();
testCStringComparison();
testCStringConversion();
testCStringStream();
testCStringSwap();
testCStringConstexpr();
testCStringNTTP();
testCStringPODUsage();
testCStringLargeCapacity();
testCStringWideChar();
return report_errors();
}
}
}
int
main()
{
return boost::static_strings::runTests();
}

View File

@@ -14,6 +14,17 @@
// Are we dependent on Boost?
// #define BOOST_STATIC_STRING_STANDALONE
#include <cstdint>
// detect 32/64 bit
#if UINTPTR_MAX == UINT64_MAX
#define BOOST_STATIC_STRING_ARCH 64
#elif UINTPTR_MAX == UINT32_MAX
#define BOOST_STATIC_STRING_ARCH 32
#else
#error Unknown or unsupported architecture, please open an issue
#endif
// Can we have deduction guides?
#if __cpp_deduction_guides >= 201703L
#define BOOST_STATIC_STRING_USE_DEDUCT
@@ -128,9 +139,6 @@
#ifndef BOOST_STATIC_STRING_THROW
#define BOOST_STATIC_STRING_THROW(ex) BOOST_THROW_EXCEPTION(ex)
#endif
#ifndef BOOST_STATIC_STRING_STATIC_ASSERT
#define BOOST_STATIC_STRING_STATIC_ASSERT(cond, msg) BOOST_STATIC_ASSERT_MSG(cond, msg)
#endif
#ifndef BOOST_STATIC_STRING_ASSERT
#define BOOST_STATIC_STRING_ASSERT(cond) BOOST_ASSERT(cond)
#endif
@@ -138,24 +146,60 @@
#ifndef BOOST_STATIC_STRING_THROW
#define BOOST_STATIC_STRING_THROW(ex) throw ex
#endif
#ifndef BOOST_STATIC_STRING_STATIC_ASSERT
#define BOOST_STATIC_STRING_STATIC_ASSERT(cond, msg) static_assert(cond, msg)
#endif
#ifndef BOOST_STATIC_STRING_ASSERT
#define BOOST_STATIC_STRING_ASSERT(cond) assert(cond)
#endif
#endif
#ifndef BOOST_STATIC_STRING_STANDALONE
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/throw_exception.hpp>
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) || \
defined(BOOST_STATIC_STRING_CXX17_STRING_VIEW)
#include <string_view>
#define BOOST_STATIC_STRING_HAS_STD_STRING_VIEW
#endif
#else
#include <cassert>
#include <stdexcept>
#if defined(__has_include)
# if !__has_include(<string_view>)
# define BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW
# endif
/*
* Replicate the logic from Boost.Config
*/
// GNU libstdc++3:
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# if ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 70100) || (__cplusplus <= 201402L)
# define BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW
# endif
// libc++:
#elif defined(_LIBCPP_VERSION)
# if (_LIBCPP_VERSION < 4000) || (__cplusplus <= 201402L)
# define BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW
# endif
// MSVC uses logic from catch all for BOOST_NO_CXX17_HDR_STRING_VIEW
// catch all:
#elif !defined(_YVALS) && !defined(_CPPLIB_VER)
# if (!defined(__has_include) || (__cplusplus < 201700))
# define BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW
# elif !__has_include(<string_view>)
# define BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW
# endif
#endif
#if !defined(BOOST_STATIC_STRING_NO_CXX17_HDR_STRING_VIEW) || \
defined(BOOST_STATIC_STRING_CXX17_STRING_VIEW)
#include <string_view>
#define BOOST_STATIC_STRING_HAS_STD_STRING_VIEW
#endif
#endif
// Compiler bug prevents constexpr from working with clang 4.x and 5.x
@@ -192,6 +236,30 @@ defined(BOOST_STATIC_STRING_CPP14)
#define BOOST_STATIC_STRING_GCC5_BAD_CONSTEXPR
#endif
#ifndef BOOST_STATIC_STRING_STANDALONE
#if ! defined(BOOST_NO_CWCHAR) && ! defined(BOOST_NO_SWPRINTF)
#define BOOST_STATIC_STRING_HAS_WCHAR
#endif
#else
#ifndef __has_include
// If we don't have __has_include in standalone,
// we will assume that <cwchar> exists.
#define BOOST_STATIC_STRING_HAS_WCHAR
#elif __has_include(<cwchar>)
#define BOOST_STATIC_STRING_HAS_WCHAR
#endif
#endif
#ifdef BOOST_STATIC_STRING_HAS_WCHAR
#include <cwchar>
#endif
// Define the basic string_view type used by the library
// Conversions to and from other available string_view types
// are still defined.
#if !defined(BOOST_STATIC_STRING_STANDALONE) || \
defined(BOOST_STATIC_STRING_HAS_STD_STRING_VIEW)
#define BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW
namespace boost {
namespace static_strings {
@@ -205,4 +273,27 @@ using basic_string_view =
#endif
} // static_strings
} // boost
#endif
#endif
#if defined(__cpp_lib_to_string) && __cpp_lib_to_string >= 202306L // std::to_[w]string() redefined in terms of std::format()
#define BOOST_STATIC_STRING_USE_STD_FORMAT
#endif
#if defined(__GNUC__) && (__GNUC__ >= 5) && (__GNUC__ <= 10) && !defined(__clang__)
// Workaround for GCC complaining about nested classes being private.
#define BOOST_STATIC_STRING_GCC_NESTED_CLASS_WORKAROUND public:
#else
#define BOOST_STATIC_STRING_GCC_NESTED_CLASS_WORKAROUND
#endif
// GCC 9 incorrectly rejects the pointer equality comparison in
// ptr_in_range() in constant expressions. GCC 10 and later handle
// it correctly.
//
// Clang 3.7 and 9-19 have the same issue.
#if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ == 9)) \
|| (defined(__clang__) && ((__clang_major__ == 3 && __clang_minor__ == 7) || ((__clang_major__ >= 9) && (__clang_major__ <= 19))))
#define BOOST_STATIC_STRING_CONSTEXPR_PTR_CMP_BROKEN
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,13 @@
],
"description": "A fixed capacity dynamically sized string.",
"category": [
"Container",
"Containers",
"String"
],
"maintainers": [
"Krystian Stasiowski <sdkrystian@gmail.com>",
"Vinnie Falco <vinnie.falco@gmail.com>"
"Alan de Freitas <alandefreitas@gmail.com>",
"Vinnie Falco <vinnie.falco@gmail.com>",
"Gennaro Prota <gennaro.prota@gmail.com>"
],
"cxxstd": "11"
}

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
# Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -7,16 +7,26 @@
# Official repository: https://github.com/boostorg/static_string
#
GroupSources (include/boost/static_string static_string)
GroupSources (test "/")
# Custom target used by the boost super-project
if(NOT TARGET tests)
add_custom_target(tests)
set_property(TARGET tests PROPERTY FOLDER _deps)
endif()
add_executable (tests
${PROJECT_FILES}
Jamfile
static_string.cpp
)
set(BOOST_STATIC_STRING_TESTS_FILES
CMakeLists.txt
Jamfile
constexpr_tests.hpp
compile_fail.hpp
static_string.cpp
)
target_link_libraries(tests
)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${BOOST_STATIC_STRING_TESTS_FILES})
add_executable(boost_static_string_tests ${BOOST_STATIC_STRING_TESTS_FILES})
set_property(TARGET tests PROPERTY FOLDER "tests")
# The include dependencies are found in the CMakeLists.txt
# of the root project directory.
# See: BOOST_STATIC_STRING_UNIT_TEST_LIBRARIES
target_link_libraries(boost_static_string_tests PRIVATE Boost::static_string)
add_test(NAME boost_static_string_tests COMMAND boost_static_string_tests)
add_dependencies(tests boost_static_string_tests)

View File

@@ -8,18 +8,21 @@
#
import testing ;
import ../../config/checks/config : requires ;
import-search /boost/config/checks ;
import config : requires ;
local defines =
[ requires
cxx11_constexpr
cxx11_decltype
cxx11_hdr_tuple
cxx11_hdr_type_traits
cxx11_template_aliases
cxx11_variadic_templates
]
;
project : requirements $(defines) ;
project : requirements $(defines)
<library>/boost/static_string//boost_static_string ;
run static_string.cpp ;

View File

@@ -0,0 +1,24 @@
# Copyright 2021-2025 Alexander Grund
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.8...3.16)
project(cmake_subdir_test LANGUAGES CXX)
# Those 2 should work the same
# while using find_package for the installed Boost avoids the need to manually specify dependencies
if(BOOST_CI_INSTALL_TEST)
find_package(boost_static_string REQUIRED)
else()
set(BOOST_INCLUDE_LIBRARIES static_string)
add_subdirectory(../../../.. deps/boost EXCLUDE_FROM_ALL)
endif()
add_executable(main main.cpp)
target_link_libraries(main Boost::static_string)
enable_testing()
add_test(NAME main COMMAND main)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

18
test/cmake_test/main.cpp Normal file
View File

@@ -0,0 +1,18 @@
//
// Copyright (c) 2025 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/static_string
//
#include <boost/static_string.hpp>
int main()
{
// Smoke test only
boost::static_string<1> s_empty;
boost::static_string<4> s_3(3, 'x');
return (s_empty.empty() && s_3.size() == 3) ? 0 : 1;
}

View File

@@ -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");

View File

@@ -22,38 +22,77 @@ 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;
// This implementation does not handle overlapping ranges where
// dest > src. A correct implementation would need to detect this
// case and copy backwards, but detecting overlap requires pointer
// comparisons that many of the tested compiles (incorrectly) refuse
// in constant expressions.
//
// Since cxper_char_traits is only used for testing constexpr
// functionality and the tests do not exercise overlapping moves
// where dest > src, this simple forward copy is sufficient.
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
@@ -67,6 +106,23 @@ bool
testConstantEvaluation()
{
#ifdef BOOST_STATIC_STRING_CPP20
// Check construction in a constexpr context
constexpr basic_static_string s("hello");
static_assert(s.size() == 5);
static_assert(s.static_capacity == 5);
static_assert(s == "hello");
// Check assignment in a constexpr context
constexpr auto s2 =
[]()
{
basic_static_string s("hello");
s = "world";
return s;
}();
static_assert(s2 == "world");
// c++20 constexpr tests
cstatic_string a;
cstatic_string b(1, 'a');
@@ -171,8 +227,10 @@ testConstantEvaluation()
a.substr(0);
#ifdef BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW
// subview
a.subview(0);
#endif
// copy
char k[20]{};
@@ -198,7 +256,8 @@ testConstantEvaluation()
a.replace(a.begin(), a.end(), a.begin(), a.end());
a.replace(a.begin(), a.end(), {'a'});
#ifdef BOOST_STATIC_STRING_IS_CONST_EVAL
#if defined(BOOST_STATIC_STRING_IS_CONST_EVAL) \
&& !defined(BOOST_STATIC_STRING_CONSTEXPR_PTR_CMP_BROKEN)
a.clear();
a.replace(a.begin(), a.end(), "a");
a.replace(a.begin(), a.end(), "a", 1);
@@ -357,8 +416,10 @@ testConstantEvaluation()
a.substr(0);
#endif
#ifdef BOOST_STATIC_STRING_HAS_STRING_VIEW
// subview
a.subview(0);
#endif
// copy
char k[20]{};
@@ -384,7 +445,8 @@ testConstantEvaluation()
a.replace(a.begin(), a.end(), a.begin(), a.end());
a.replace(a.begin(), a.end(), {'a'});
#ifdef BOOST_STATIC_STRING_IS_CONST_EVAL
#if defined(BOOST_STATIC_STRING_IS_CONST_EVAL) \
&& !defined(BOOST_STATIC_STRING_CONSTEXPR_PTR_CMP_BROKEN)
a.clear();
a.replace(a.begin(), a.end(), "a");
a.replace(a.begin(), a.end(), "a", 1);
@@ -556,7 +618,8 @@ testConstantEvaluation()
a.replace(a.begin(), a.end(), a.begin(), a.end());
a.replace(a.begin(), a.end(), {'a'});
#ifdef BOOST_STATIC_STRING_IS_CONST_EVAL
#if defined(BOOST_STATIC_STRING_IS_CONST_EVAL) \
&& !defined(BOOST_STATIC_STRING_CONSTEXPR_PTR_CMP_BROKEN)
a.clear();
a.replace(a.begin(), a.end(), "a");
a.replace(a.begin(), a.end(), "a", 1);
@@ -603,5 +666,28 @@ testConstantEvaluation()
cstatic_string().empty();
#endif
}
#if __cpp_nontype_template_args >= 201911L
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
} // boost

File diff suppressed because it is too large Load Diff