Compare commits

...

16 Commits

Author SHA1 Message Date
Peter Dimov
1dcc441ca1 Remove windows-2019 from GHA 2025-08-16 11:30:43 +03:00
Peter Dimov
cdf118b15b Avoid msvc-14.2 Appveyor timeout 2025-08-16 10:03:54 +03:00
Peter Dimov
ab75e1f892 Update appveyor.yml 2025-08-15 20:09:22 +03:00
Peter Dimov
dcfb560de3 Add msvc-14.2 to appveyor.yml 2025-08-15 19:51:08 +03:00
Peter Dimov
362fb1d677 Update appveyor.yml 2025-08-15 19:15:52 +03:00
Peter Dimov
79dac0e691 Merge pull request #118 from RedBeard0531/features/constexpr
Enable C++20 constexpr for intrusive_ptr
2025-05-10 11:52:28 +03:00
Mathias Stearn
d08d035bdf Enable C++20 constexpr for intrusive_ptr
fixes #117
2025-05-09 22:37:02 +02:00
Peter Dimov
709e446968 Update ci.yml 2025-05-08 16:04:15 +03:00
Peter Dimov
0b0924ff82 Update revision history 2025-01-15 19:40:28 +02:00
Peter Dimov
e7433ba545 Fix operator<< for shared_ptr and intrusive_ptr. Fixes #115. 2025-01-13 16:13:04 +02:00
Peter Dimov
785a17aaaf Add wide stream tests. Refs #115. 2025-01-13 16:12:31 +02:00
Peter Dimov
576d31f206 Add sp_ostream_test, ip_ostream_test, lsp_ostream_test 2025-01-13 15:24:45 +02:00
Peter Dimov
1b89a64e9b Add missing inline to boost::detail::lw_thread_routine to prevent multiple definition errors. 2025-01-07 21:31:20 +02:00
Peter Dimov
840e2ff1a8 Update .drone.jsonnet 2024-12-14 05:42:59 +02:00
Peter Dimov
622e2c3f83 Apply Node20 workaround 2024-12-14 05:41:18 +02:00
Peter Dimov
0630607f39 Update ci.yml 2024-12-14 05:40:47 +02:00
13 changed files with 480 additions and 109 deletions

View File

@@ -179,22 +179,22 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 23.04 GCC 13 32 ASAN", "Linux 24.04 GCC 13 32 ASAN",
"cppalliance/droneubuntu2304:1", "cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + asan, { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + asan,
"g++-13-multilib", "g++-13-multilib",
), ),
linux_pipeline( linux_pipeline(
"Linux 23.04 GCC 13 32 UBSAN", "Linux 24.04 GCC 13 32 UBSAN",
"cppalliance/droneubuntu2304:1", "cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + ubsan, { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + ubsan,
"g++-13-multilib", "g++-13-multilib",
), ),
linux_pipeline( linux_pipeline(
"Linux 23.04 GCC 13 64 UBSAN", "Linux 24.04 GCC 13 64 UBSAN",
"cppalliance/droneubuntu2304:1", "cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + ubsan, { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + ubsan,
"g++-13-multilib", "g++-13-multilib",
), ),
@@ -333,22 +333,22 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
), ),
linux_pipeline( linux_pipeline(
"Linux 23.04 Clang 16", "Linux 24.04 Clang 16",
"cppalliance/droneubuntu2304:1", "cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' }, { TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' },
"clang-16", "clang-16",
), ),
linux_pipeline( linux_pipeline(
"Linux 23.10 Clang 17 UBSAN", "Linux 24.04 Clang 17 UBSAN",
"cppalliance/droneubuntu2310:1", "cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + ubsan, { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + ubsan,
"clang-17", "clang-17",
), ),
linux_pipeline( linux_pipeline(
"Linux 23.10 Clang 17 ASAN", "Linux 24.04 Clang 17 ASAN",
"cppalliance/droneubuntu2310:1", "cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + asan, { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + asan,
"clang-17", "clang-17",
), ),
@@ -367,6 +367,13 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
"clang-18", "clang-18",
), ),
linux_pipeline(
"Linux 24.10 Clang 19",
"cppalliance/droneubuntu2410:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '11,14,17,20,2b' },
"clang-19",
),
macos_pipeline( macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN", "MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + ubsan, { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + ubsan,

View File

@@ -19,41 +19,44 @@ jobs:
include: include:
- toolset: gcc-4.8 - toolset: gcc-4.8
cxxstd: "11" cxxstd: "11"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: g++-4.8-multilib install: g++-4.8-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-5 - toolset: gcc-5
cxxstd: "11,14,1z" cxxstd: "11,14,1z"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: g++-5-multilib install: g++-5-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-6 - toolset: gcc-6
cxxstd: "11,14,1z" cxxstd: "11,14,1z"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: g++-6-multilib install: g++-6-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-7 - toolset: gcc-7
cxxstd: "11,14,17" cxxstd: "11,14,17"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: g++-7-multilib install: g++-7-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-8 - toolset: gcc-8
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: g++-8-multilib install: g++-8-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-9 - toolset: gcc-9
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: g++-9-multilib install: g++-9-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-10 - toolset: gcc-10
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: g++-10-multilib install: g++-10-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-11 - toolset: gcc-11
@@ -69,65 +72,81 @@ jobs:
- toolset: gcc-13 - toolset: gcc-13
cxxstd: "11,14,17,20,2b" cxxstd: "11,14,17,20,2b"
os: ubuntu-latest os: ubuntu-latest
container: ubuntu:23.04 container: ubuntu:24.04
install: g++-13-multilib install: g++-13-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-14 - toolset: gcc-14
cxxstd: "11,14,17,20,2b" cxxstd: "11,14,17,20,23,2c"
os: ubuntu-latest os: ubuntu-latest
container: ubuntu:24.04 container: ubuntu:24.04
install: g++-14-multilib install: g++-14-multilib
address-model: 32,64 address-model: 32,64
- toolset: gcc-15
cxxstd: "11,14,17,20,23,2c"
os: ubuntu-latest
container: ubuntu:25.04
install: g++-15-multilib
address-model: 32,64
- toolset: clang - toolset: clang
compiler: clang++-3.9 compiler: clang++-3.9
cxxstd: "11,14" cxxstd: "11,14"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: clang-3.9 install: clang-3.9
- toolset: clang - toolset: clang
compiler: clang++-4.0 compiler: clang++-4.0
cxxstd: "11,14" cxxstd: "11,14"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: clang-4.0 install: clang-4.0
- toolset: clang - toolset: clang
compiler: clang++-5.0 compiler: clang++-5.0
cxxstd: "11,14,1z" cxxstd: "11,14,1z"
os: ubuntu-latest
container: ubuntu:18.04 container: ubuntu:18.04
os: ubuntu-latest
install: clang-5.0 install: clang-5.0
- toolset: clang - toolset: clang
compiler: clang++-6.0 compiler: clang++-6.0
cxxstd: "11,14,17" cxxstd: "11,14,17"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-6.0 install: clang-6.0
- toolset: clang - toolset: clang
compiler: clang++-7 compiler: clang++-7
cxxstd: "11,14,17" cxxstd: "11,14,17"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-7 install: clang-7
- toolset: clang - toolset: clang
compiler: clang++-8 compiler: clang++-8
cxxstd: "11,14,17" cxxstd: "11,14,17"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-8 install: clang-8
- toolset: clang - toolset: clang
compiler: clang++-9 compiler: clang++-9
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-9 install: clang-9
- toolset: clang - toolset: clang
compiler: clang++-10 compiler: clang++-10
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-10
- toolset: clang - toolset: clang
compiler: clang++-11 compiler: clang++-11
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-11
- toolset: clang - toolset: clang
compiler: clang++-12 compiler: clang++-12
cxxstd: "11,14,17,20" cxxstd: "11,14,17,20"
os: ubuntu-20.04 container: ubuntu:20.04
os: ubuntu-latest
install: clang-12
- toolset: clang - toolset: clang
compiler: clang++-13 compiler: clang++-13
cxxstd: "11,14,17,20,2b" cxxstd: "11,14,17,20,2b"
@@ -149,13 +168,13 @@ jobs:
- toolset: clang - toolset: clang
compiler: clang++-16 compiler: clang++-16
cxxstd: "11,14,17,20,2b" cxxstd: "11,14,17,20,2b"
container: ubuntu:23.04 container: ubuntu:24.04
os: ubuntu-latest os: ubuntu-latest
install: clang-16 install: clang-16
- toolset: clang - toolset: clang
compiler: clang++-17 compiler: clang++-17
cxxstd: "11,14,17,20,2b" cxxstd: "11,14,17,20,2b"
container: ubuntu:23.10 container: ubuntu:24.04
os: ubuntu-latest os: ubuntu-latest
install: clang-17 install: clang-17
- toolset: clang - toolset: clang
@@ -164,6 +183,18 @@ jobs:
container: ubuntu:24.04 container: ubuntu:24.04
os: ubuntu-latest os: ubuntu-latest
install: clang-18 install: clang-18
- toolset: clang
compiler: clang++-19
cxxstd: "11,14,17,20,23,2c"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-19
- toolset: clang
compiler: clang++-20
cxxstd: "11,14,17,20,23,2c"
container: ubuntu:25.04
os: ubuntu-latest
install: clang-20
- toolset: clang - toolset: clang
cxxstd: "11,14,17,20,2b" cxxstd: "11,14,17,20,2b"
os: macos-13 os: macos-13
@@ -175,24 +206,32 @@ jobs:
os: macos-15 os: macos-15
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
container: ${{matrix.container}}
container:
image: ${{matrix.container}}
volumes:
- /node20217:/node20217:rw,rshared
- ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }}
defaults: defaults:
run: run:
shell: bash shell: bash
steps: steps:
- name: Enable Node 16
run: |
echo "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true" >> $GITHUB_ENV
- uses: actions/checkout@v3
- name: Setup container environment - name: Setup container environment
if: matrix.container if: matrix.container
run: | run: |
apt-get update apt-get update
apt-get -y install sudo python3 git g++ apt-get -y install sudo python3 git g++ curl xz-utils
- name: Install nodejs20glibc2.17
if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }}
run: |
curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz
tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217
ldd /__e/node20/bin/node
- uses: actions/checkout@v4
- name: Install packages - name: Install packages
if: matrix.install if: matrix.install
@@ -237,14 +276,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- toolset: msvc-14.0
cxxstd: 14,latest
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3 - toolset: msvc-14.3
cxxstd: "14,17,20,latest" cxxstd: "14,17,20,latest"
addrmd: 32,64 addrmd: 32,64
@@ -256,7 +287,7 @@ jobs:
- toolset: gcc - toolset: gcc
cxxstd: "11,14,17,2a" cxxstd: "11,14,17,2a"
addrmd: 64 addrmd: 64
os: windows-2019 os: windows-2022
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@@ -296,7 +327,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: ubuntu-20.04
- os: ubuntu-22.04 - os: ubuntu-22.04
- os: ubuntu-24.04 - os: ubuntu-24.04
- os: macos-13 - os: macos-13
@@ -345,7 +375,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: ubuntu-20.04
- os: ubuntu-22.04 - os: ubuntu-22.04
- os: ubuntu-24.04 - os: ubuntu-24.04
- os: macos-13 - os: macos-13
@@ -404,7 +433,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: ubuntu-20.04
- os: ubuntu-22.04 - os: ubuntu-22.04
- os: ubuntu-24.04 - os: ubuntu-24.04
- os: macos-13 - os: macos-13
@@ -461,8 +489,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: windows-2019 - os: windows-latest
- os: windows-2022
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@@ -510,8 +537,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: windows-2019 - os: windows-latest
- os: windows-2022
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@@ -577,8 +603,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: windows-2019 - os: windows-latest
- os: windows-2022
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}

View File

@@ -21,6 +21,22 @@ environment:
TOOLSET: msvc-14.1 TOOLSET: msvc-14.1
CXXSTD: 14,17 CXXSTD: 14,17
ADDRMD: 32,64 ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 14
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 20
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: latest
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win TOOLSET: clang-win
CXXSTD: 14,17,latest CXXSTD: 14,17,latest
@@ -33,14 +49,14 @@ environment:
ADDPATH: C:\cygwin64\bin; ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 11,14,1z CXXSTD: 11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\mingw\bin; ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 11,14,1z CXXSTD: 11,14,17
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin; ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 11,14,1z CXXSTD: 11,14,17
install: install:
- set BOOST_BRANCH=develop - set BOOST_BRANCH=develop

View File

@@ -1,5 +1,5 @@
//// ////
Copyright 2019, 2020 Peter Dimov Copyright 2019-2025 Peter Dimov
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@@ -13,6 +13,10 @@ http://www.boost.org/LICENSE_1_0.txt
:toc-title: :toc-title:
:idprefix: changelog_ :idprefix: changelog_
## Changes in 1.88.0
* Fix `operator<<` for wide streams (accidentally broken in 1.87.0)
## Changes in 1.87.0 ## Changes in 1.87.0
* {cpp}03 is no longer supported, a {cpp}11 compiler is required. * {cpp}03 is no longer supported, a {cpp}11 compiler is required.

View File

@@ -104,7 +104,7 @@ public:
#if defined( BOOST_HAS_PTHREADS ) #if defined( BOOST_HAS_PTHREADS )
extern "C" void * lw_thread_routine( void * pv ) extern "C" inline void * lw_thread_routine( void * pv )
{ {
std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) ); std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
@@ -115,7 +115,7 @@ extern "C" void * lw_thread_routine( void * pv )
#else #else
unsigned __stdcall lw_thread_routine( void * pv ) inline unsigned __stdcall lw_thread_routine( void * pv )
{ {
std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) ); std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );

View File

@@ -0,0 +1,37 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_CXX20_CONSTEXPR_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_CXX20_CONSTEXPR_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
// detail/sp_noexcept.hpp
//
// Copyright 2025 Mathias Stearn
//
// 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
// This macro is used to mark functions as constexpr if the compiler supports
// constexpr destructors. Since you can't have a constexpr smart pointer object,
// everything except null constructors are guided behind this macro. Because
// this also guards a use of dynamic_cast, we need to check for its availability
// as well. It isn't worth splitting out since all known compilers that support
// constexpr dynamic_cast also support constexpr destructors.
//
// WARNING: This does not check for changing active member of a union in
// constant expressions which is allowed in C++20. If that is needed, we
// need to raise the checked version to 202002L.
#if defined(__cpp_constexpr_dynamic_alloc) && __cpp_constexpr_dynamic_alloc >= 201907L \
&& defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
#define BOOST_SP_CXX20_CONSTEXPR constexpr
#else
#define BOOST_SP_CXX20_CONSTEXPR
#define BOOST_SP_NO_CXX20_CONSTEXPR
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CXX20_CONSTEXPR_HPP_INCLUDED

View File

@@ -13,6 +13,7 @@
// See http://www.boost.org/libs/smart_ptr/ for documentation. // See http://www.boost.org/libs/smart_ptr/ for documentation.
// //
#include <boost/smart_ptr/detail/sp_cxx20_constexpr.hpp>
#include <boost/smart_ptr/detail/sp_convertible.hpp> #include <boost/smart_ptr/detail/sp_convertible.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp> #include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
@@ -53,29 +54,29 @@ public:
{ {
} }
intrusive_ptr( T * p, bool add_ref = true ): px( p ) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr( T * p, bool add_ref = true ): px( p )
{ {
if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
} }
template<class U> template<class U>
intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() ) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
: px( rhs.get() ) : px( rhs.get() )
{ {
if( px != 0 ) intrusive_ptr_add_ref( px ); if( px != 0 ) intrusive_ptr_add_ref( px );
} }
intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
{ {
if( px != 0 ) intrusive_ptr_add_ref( px ); if( px != 0 ) intrusive_ptr_add_ref( px );
} }
~intrusive_ptr() BOOST_SP_CXX20_CONSTEXPR ~intrusive_ptr()
{ {
if( px != 0 ) intrusive_ptr_release( px ); if( px != 0 ) intrusive_ptr_release( px );
} }
template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs) template<class U> BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
{ {
this_type(rhs).swap(*this); this_type(rhs).swap(*this);
return *this; return *this;
@@ -83,12 +84,12 @@ public:
// Move support // Move support
intrusive_ptr(intrusive_ptr && rhs) noexcept : px( rhs.px ) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr && rhs) noexcept : px( rhs.px )
{ {
rhs.px = 0; rhs.px = 0;
} }
intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept
{ {
this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this); this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
return *this; return *this;
@@ -97,76 +98,76 @@ public:
template<class U> friend class intrusive_ptr; template<class U> friend class intrusive_ptr;
template<class U> template<class U>
intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty()) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
: px( rhs.px ) : px( rhs.px )
{ {
rhs.px = 0; rhs.px = 0;
} }
template<class U> template<class U>
intrusive_ptr & operator=(intrusive_ptr<U> && rhs) noexcept BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr<U> && rhs) noexcept
{ {
this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this); this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
return *this; return *this;
} }
intrusive_ptr & operator=(intrusive_ptr const & rhs) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr const & rhs)
{ {
this_type(rhs).swap(*this); this_type(rhs).swap(*this);
return *this; return *this;
} }
intrusive_ptr & operator=(T * rhs) BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(T * rhs)
{ {
this_type(rhs).swap(*this); this_type(rhs).swap(*this);
return *this; return *this;
} }
void reset() BOOST_SP_CXX20_CONSTEXPR void reset()
{ {
this_type().swap( *this ); this_type().swap( *this );
} }
void reset( T * rhs ) BOOST_SP_CXX20_CONSTEXPR void reset( T * rhs )
{ {
this_type( rhs ).swap( *this ); this_type( rhs ).swap( *this );
} }
void reset( T * rhs, bool add_ref ) BOOST_SP_CXX20_CONSTEXPR void reset( T * rhs, bool add_ref )
{ {
this_type( rhs, add_ref ).swap( *this ); this_type( rhs, add_ref ).swap( *this );
} }
T * get() const noexcept BOOST_SP_CXX20_CONSTEXPR T * get() const noexcept
{ {
return px; return px;
} }
T * detach() noexcept BOOST_SP_CXX20_CONSTEXPR T * detach() noexcept
{ {
T * ret = px; T * ret = px;
px = 0; px = 0;
return ret; return ret;
} }
T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_CXX20_CONSTEXPR T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
{ {
BOOST_ASSERT( px != 0 ); BOOST_ASSERT( px != 0 );
return *px; return *px;
} }
T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_CXX20_CONSTEXPR T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
{ {
BOOST_ASSERT( px != 0 ); BOOST_ASSERT( px != 0 );
return px; return px;
} }
explicit operator bool () const noexcept BOOST_SP_CXX20_CONSTEXPR explicit operator bool () const noexcept
{ {
return px != 0; return px != 0;
} }
void swap(intrusive_ptr & rhs) noexcept BOOST_SP_CXX20_CONSTEXPR void swap(intrusive_ptr & rhs) noexcept
{ {
T * tmp = px; T * tmp = px;
px = rhs.px; px = rhs.px;
@@ -178,101 +179,101 @@ private:
T * px; T * px;
}; };
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
{ {
return a.get() == b.get(); return a.get() == b.get();
} }
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
{ {
return a.get() != b.get(); return a.get() != b.get();
} }
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(intrusive_ptr<T> const & a, U * b) noexcept
{ {
return a.get() == b; return a.get() == b;
} }
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept
{ {
return a.get() != b; return a.get() != b;
} }
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(T * a, intrusive_ptr<U> const & b) noexcept
{ {
return a == b.get(); return a == b.get();
} }
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept
{ {
return a != b.get(); return a != b.get();
} }
template<class T> inline bool operator==( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator==( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
{ {
return p.get() == 0; return p.get() == 0;
} }
template<class T> inline bool operator==( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator==( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
{ {
return p.get() == 0; return p.get() == 0;
} }
template<class T> inline bool operator!=( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
{ {
return p.get() != 0; return p.get() != 0;
} }
template<class T> inline bool operator!=( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
{ {
return p.get() != 0; return p.get() != 0;
} }
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept
{ {
return std::less<T *>()(a.get(), b.get()); return std::less<T *>()(a.get(), b.get());
} }
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept
{ {
lhs.swap(rhs); lhs.swap(rhs);
} }
// mem_fn support // mem_fn support
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept template<class T> BOOST_SP_CXX20_CONSTEXPR inline T * get_pointer(intrusive_ptr<T> const & p) noexcept
{ {
return p.get(); return p.get();
} }
// pointer casts // pointer casts
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p) template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{ {
return static_cast<T *>(p.get()); return static_cast<T *>(p.get());
} }
template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p) template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
{ {
return const_cast<T *>(p.get()); return const_cast<T *>(p.get());
} }
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p) template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
{ {
return dynamic_cast<T *>(p.get()); return dynamic_cast<T *>(p.get());
} }
template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) noexcept
{ {
return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false ); return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
} }
template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) noexcept
{ {
return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false ); return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
} }
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) noexcept template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) noexcept
{ {
T * p2 = dynamic_cast<T*>( p.get() ); T * p2 = dynamic_cast<T*>( p.get() );
@@ -285,7 +286,7 @@ template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<
// operator<< // operator<<
template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p) template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
{ {
os << p.get(); os << p.get();
return os; return os;

View File

@@ -775,7 +775,7 @@ template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shar
// operator<< // operator<<
template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p) template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
{ {
os << p.get(); os << p.get();
return os; return os;

View File

@@ -245,6 +245,7 @@ run atomic_sp_test.cpp ;
run sp_constexpr_test.cpp ; run sp_constexpr_test.cpp ;
run sp_constexpr_test2.cpp ; run sp_constexpr_test2.cpp ;
compile ip_constexpr_test.cpp ;
run atomic_sp_constexpr_test.cpp ; run atomic_sp_constexpr_test.cpp ;
@@ -424,3 +425,7 @@ run sp_is_bounded_array_test.cpp ;
run sp_is_unbounded_array_test.cpp ; run sp_is_unbounded_array_test.cpp ;
run sp_type_identity_test.cpp ; run sp_type_identity_test.cpp ;
run sp_type_with_alignment_test.cpp ; run sp_type_with_alignment_test.cpp ;
run sp_ostream_test.cpp ;
run ip_ostream_test.cpp ;
run lsp_ostream_test.cpp ;

133
test/ip_constexpr_test.cpp Normal file
View File

@@ -0,0 +1,133 @@
//
// ip_constexpr_test.cpp
//
// Copyright 2025 Mathias Stearn
//
// 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
//
#include <boost/intrusive_ptr.hpp>
#ifndef BOOST_SP_NO_CXX20_CONSTEXPR
struct dummy {
// no-ops, so safe on pointers to static constexpr variables
friend constexpr void intrusive_ptr_add_ref(const dummy *) {}
friend constexpr void intrusive_ptr_release(const dummy *) {}
};
static constexpr dummy d;
struct subdummy : dummy {};
// Test that basic operations work at compile time.
static_assert(bool(boost::intrusive_ptr<const dummy>(&d)));
static_assert(!bool(boost::intrusive_ptr<dummy>(nullptr)));
static_assert(!bool(boost::intrusive_ptr<dummy>()));
static_assert(!bool(boost::intrusive_ptr<dummy>(boost::intrusive_ptr<subdummy>())));
static_assert(&*boost::intrusive_ptr<const dummy>(&d) == &d);
static_assert(boost::intrusive_ptr<const dummy>(&d).operator->() == &d);
static_assert(boost::intrusive_ptr<dummy>() == nullptr);
static_assert(boost::intrusive_ptr<dummy>() == boost::intrusive_ptr<dummy>(nullptr));
static_assert(boost::intrusive_ptr<dummy>() != boost::intrusive_ptr<const dummy>(&d));
static_assert(boost::intrusive_ptr<const dummy>(&d) != nullptr);
static_assert(boost::intrusive_ptr<const dummy>(&d) == boost::intrusive_ptr<const dummy>(&d));
static_assert(boost::intrusive_ptr<const dummy>(&d) == boost::intrusive_ptr<const dummy>(&d).get());
static_assert(boost::intrusive_ptr<const dummy>(&d) == boost::intrusive_ptr<const dummy>(&d).detach());
static_assert(!(boost::intrusive_ptr<const dummy>(&d) < boost::intrusive_ptr<const dummy>(&d)));
static_assert(boost::get_pointer(boost::intrusive_ptr<const dummy>(&d)) == &d);
static_assert(boost::static_pointer_cast<const dummy>( boost::intrusive_ptr<const dummy>(&d)) == &d);
static_assert(boost::const_pointer_cast<const dummy>( boost::intrusive_ptr<const dummy>(&d)) == &d);
static_assert(boost::dynamic_pointer_cast<const dummy>( boost::intrusive_ptr<const dummy>(&d)) == &d);
constexpr auto lvalue = boost::intrusive_ptr<const dummy>(&d);
constexpr auto lvalue_convertible = boost::intrusive_ptr<const subdummy>();
static_assert(boost::intrusive_ptr<const dummy>(lvalue) == &d);
static_assert(!boost::intrusive_ptr<const dummy>(lvalue_convertible));
static_assert(boost::static_pointer_cast<const dummy>(lvalue) == &d);
static_assert(boost::const_pointer_cast<const dummy>(lvalue) == &d);
static_assert(boost::dynamic_pointer_cast<const dummy>(lvalue) == &d);
// Works in places that static_assert doesn't, like expressions with
// non-constexpr variables in constexpr functions.
template <typename T> constexpr void semi_static_assert(T b) {
if (!b)
throw "assertion failed"; // Not constexpr so fails compile.
}
constexpr bool test_swap() {
auto p1 = boost::intrusive_ptr<const dummy>(&d);
auto p2 = boost::intrusive_ptr<const dummy>();
swap(p1, p2);
semi_static_assert(!p1 && p2);
p1.swap(p2);
semi_static_assert(p1 && !p2);
return true;
}
static_assert(test_swap());
constexpr bool test_reset_assign() {
// Test assignments resulting in nullptr
{
auto p1 = boost::intrusive_ptr<const dummy>(&d);
p1.reset();
semi_static_assert(!p1);
}
{
auto p1 = boost::intrusive_ptr<const dummy>(&d);
p1.reset(nullptr);
semi_static_assert(!p1);
}
{
auto p1 = boost::intrusive_ptr<const dummy>(&d);
p1 = nullptr;
semi_static_assert(!p1);
}
{
auto p1 = boost::intrusive_ptr<const dummy>(&d);
p1 = boost::intrusive_ptr<const dummy>();
semi_static_assert(!p1);
}
{
auto p1 = boost::intrusive_ptr<const dummy>(&d);
p1 = boost::intrusive_ptr<subdummy>();
semi_static_assert(!p1);
}
{
auto p1 = boost::intrusive_ptr<const dummy>(&d);
p1 = lvalue_convertible;
semi_static_assert(!p1);
}
// Test assignments resulting in &d
{
auto p1 = boost::intrusive_ptr<const dummy>();
p1.reset(&d);
semi_static_assert(p1 == &d);
}
{
auto p1 = boost::intrusive_ptr<const dummy>();
p1.reset(&d, true);
semi_static_assert(p1 == &d);
}
{
auto p1 = boost::intrusive_ptr<const dummy>();
p1 = boost::intrusive_ptr<const dummy>(&d);
semi_static_assert(p1 == &d);
}
{
auto p1 = boost::intrusive_ptr<const dummy>();
p1 = lvalue;
semi_static_assert(p1 == &d);
}
{
auto p1 = boost::intrusive_ptr<const dummy>();
p1 = &d;
semi_static_assert(p1 == &d);
}
return true;
}
static_assert(test_reset_assign());
#endif

75
test/ip_ostream_test.cpp Normal file
View File

@@ -0,0 +1,75 @@
// Copyright 2011, 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/intrusive_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <sstream>
class base
{
private:
int use_count_;
base(base const &);
base & operator=(base const &);
protected:
base(): use_count_(0)
{
}
virtual ~base()
{
}
public:
long use_count() const
{
return use_count_;
}
inline friend void intrusive_ptr_add_ref(base * p)
{
++p->use_count_;
}
inline friend void intrusive_ptr_release(base * p)
{
if(--p->use_count_ == 0) delete p;
}
};
struct X: public base
{
};
template<class T> std::string to_string( T const& t )
{
std::ostringstream os;
os << t;
return os.str();
}
template<class T> std::wstring to_wstring( T const& t )
{
std::wostringstream os;
os << t;
return os.str();
}
int main()
{
boost::intrusive_ptr<X> p1, p2( new X );
BOOST_TEST_EQ( to_string( p1 ), to_string( p1.get() ) );
BOOST_TEST_EQ( to_string( p2 ), to_string( p2.get() ) );
BOOST_TEST( to_wstring( p1 ) == to_wstring( p1.get() ) );
BOOST_TEST( to_wstring( p2 ) == to_wstring( p2.get() ) );
return boost::report_errors();
}

34
test/lsp_ostream_test.cpp Normal file
View File

@@ -0,0 +1,34 @@
// Copyright 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <sstream>
template<class T> std::string to_string( T const& t )
{
std::ostringstream os;
os << t;
return os.str();
}
template<class T> std::wstring to_wstring( T const& t )
{
std::wostringstream os;
os << t;
return os.str();
}
int main()
{
boost::local_shared_ptr<int> p1, p2( new int );
BOOST_TEST_EQ( to_string( p1 ), to_string( p1.get() ) );
BOOST_TEST_EQ( to_string( p2 ), to_string( p2.get() ) );
BOOST_TEST( to_wstring( p1 ) == to_wstring( p1.get() ) );
BOOST_TEST( to_wstring( p2 ) == to_wstring( p2.get() ) );
return boost::report_errors();
}

34
test/sp_ostream_test.cpp Normal file
View File

@@ -0,0 +1,34 @@
// Copyright 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <sstream>
template<class T> std::string to_string( T const& t )
{
std::ostringstream os;
os << t;
return os.str();
}
template<class T> std::wstring to_wstring( T const& t )
{
std::wostringstream os;
os << t;
return os.str();
}
int main()
{
boost::shared_ptr<int> p1, p2( new int );
BOOST_TEST_EQ( to_string( p1 ), to_string( p1.get() ) );
BOOST_TEST_EQ( to_string( p2 ), to_string( p2.get() ) );
BOOST_TEST( to_wstring( p1 ) == to_wstring( p1.get() ) );
BOOST_TEST( to_wstring( p2 ) == to_wstring( p2.get() ) );
return boost::report_errors();
}