Compare commits

..

19 Commits

Author SHA1 Message Date
Andrey Semashev a90a31934f Remove dependencies on Boost.StaticAssert.
Boost.StaticAssert has been merged into Boost.Config, so replace
the dependency accordingly.
2026-01-22 15:21:40 +03:00
Peter Dimov f3cae495d3 Document is_placeholder 2026-01-02 13:40:47 +02:00
Peter Dimov 8c338d5a65 Add boost/is_placeholder.hpp (moved from Bind) 2026-01-02 13:22:31 +02:00
Peter Dimov 89b242e540 Add VS2026 to Drone 2025-12-25 16:31:01 +02:00
Peter Dimov c4e5a6541f Add a test_output_impl overload for char8_t 2025-12-25 15:05:02 +02:00
Peter Dimov abb1b9ce5b Add char8_t tests to lightweight_test_test6 2025-12-25 14:57:51 +02:00
Peter Dimov a35b0620a9 Update .drone.jsonnet 2025-12-21 20:13:06 +02:00
Peter Dimov f3cd3afb69 Specialize output for all pointer types; fixes EQ w/ wchar_t* et al 2025-12-21 19:02:50 +02:00
Peter Dimov 378dc90a73 Add lightweight_test_eq_ptr; tests EQ and NE with various pointer types. 2025-12-21 18:46:12 +02:00
Peter Dimov cc765abfc6 Split clang-win job in appveyor.yml to avoid timeout 2025-12-14 22:45:57 +02:00
Peter Dimov b7fdbf41a7 Add benchmark/sv_find_first_of.cpp, sv_find_first_not_of.cpp 2025-12-14 21:41:12 +02:00
Peter Dimov 5bea3b85e6 Add macos-26, clang-21 to ci.yml 2025-12-14 20:56:55 +02:00
Andrey Semashev b0bae8a8ae Removed macos-13 from GitHub Actions.
The macos-13 image is retierd.

Also, clang on macos-15 supports C++23.
2025-12-13 20:35:43 +03:00
Andrey Semashev 99d550a5e4 Mention that null_deleter can be useful when the object doesn't need to be deallocated. 2025-12-08 14:18:15 +03:00
Peter Dimov 239953da9f Remove Clang 3.5, 3.6 from GHA 2025-10-27 02:24:45 +02:00
Peter Dimov 52831a4fd9 Remove VS2017 Clang from Appveyor 2025-10-26 20:51:36 +02:00
Glen Fernandes b852430614 Update formatting to be consistent with rest of span 2025-10-25 14:55:53 -04:00
Peter Dimov ed46bfacff Merge pull request #203 from ashtum/develop
detail::span_convertible handles void types
2025-10-24 11:36:04 +03:00
Mohammad Nejati 6afe70e09d detail::span_convertible handles void types
fixes #202
2025-09-08 17:02:46 +00:00
18 changed files with 864 additions and 56 deletions
+24 -11
View File
@@ -382,26 +382,33 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
linux_pipeline(
"Linux 24.04 Clang 19 UBSAN",
"Linux 24.04 Clang 19",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '03,11,14,17,20,2b' } + ubsan,
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '03,11,14,17,20,2b' },
"clang-19",
),
linux_pipeline(
"Linux 24.04 Clang 19 ASAN",
"Linux 24.04 Clang 20 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '03,11,14,17,20,2b' } + asan,
"clang-19",
),
linux_pipeline(
"Linux 25.04 Clang 20",
"cppalliance/droneubuntu2504:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '03,11,14,17,20,23,2c' },
{ TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '03,11,14,17,20,23,2c' } + ubsan,
"clang-20",
),
linux_pipeline(
"Linux 24.04 Clang 20 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '03,11,14,17,20,23,2c' } + asan,
"clang-20",
),
linux_pipeline(
"Linux 25.10 Clang 21",
"cppalliance/droneubuntu2510:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-21', CXXSTD: '03,11,14,17,20,23,2c' },
"clang-21",
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + ubsan,
@@ -447,4 +454,10 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
"cppalliance/dronevs2022:1",
{ TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest', ADDRMD: '32,64' },
),
windows_pipeline(
"Windows VS2026 msvc-14.5",
"cppalliance/dronevs2026:1",
{ TOOLSET: 'msvc-14.5', CXXSTD: '14,17,20,latest', ADDRMD: '32,64' },
),
]
+21 -24
View File
@@ -151,20 +151,6 @@ jobs:
- g++-12
# Linux, clang
- toolset: clang
compiler: clang++-3.5
cxxstd: "03,11"
os: ubuntu-latest
container: ubuntu:16.04
install:
- clang-3.5
- toolset: clang
compiler: clang++-3.6
cxxstd: "03,11,14"
os: ubuntu-latest
container: ubuntu:16.04
install:
- clang-3.6
- toolset: clang
compiler: clang++-3.7
cxxstd: "03,11,14"
@@ -334,15 +320,26 @@ jobs:
linkflags: -stdlib=libc++
- toolset: clang
compiler: clang++-20
cxxstd: "03,11,14,17,20,2b,2c"
cxxstd: "03,11,14,17,20,23,2c"
os: ubuntu-latest
container: ubuntu:25.04
container: ubuntu:24.04
install:
- clang-20
- libc++-20-dev
- libc++abi-20-dev
cxxflags: -stdlib=libc++
linkflags: -stdlib=libc++
- toolset: clang
compiler: clang++-21
cxxstd: "03,11,14,17,20,23,2c"
os: ubuntu-latest
container: ubuntu:25.10
install:
- clang-21
- libc++-21-dev
- libc++abi-21-dev
cxxflags: -stdlib=libc++
linkflags: -stdlib=libc++
- name: UBSAN
toolset: clang
compiler: clang++-15
@@ -365,14 +362,14 @@ jobs:
- g++-13
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-13
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-14
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
- toolset: clang
os: macos-15
cxxstd: "03,11,14,17,20,23,2c"
- toolset: clang
os: macos-26
cxxstd: "03,11,14,17,20,23,2c"
timeout-minutes: 45
runs-on: ${{matrix.os}}
@@ -680,9 +677,9 @@ jobs:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
- os: macos-26
runs-on: ${{matrix.os}}
timeout-minutes: 10
@@ -747,9 +744,9 @@ jobs:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
- os: macos-26
runs-on: ${{matrix.os}}
timeout-minutes: 10
@@ -824,9 +821,9 @@ jobs:
include:
- os: ubuntu-22.04
- os: ubuntu-24.04
- os: macos-13
- os: macos-14
- os: macos-15
- os: macos-26
runs-on: ${{matrix.os}}
timeout-minutes: 20
+3 -5
View File
@@ -27,17 +27,15 @@ environment:
ADDRMD: 32,64
CXXSTD: 14,17
# clang-win 32 bit fails to link with "unable to load mspdbcore.dll (error code: 126)"
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
ADDRMD: 64
CXXSTD: 14,17,latest
CXXSTD: 14,17
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
ADDRMD: 64
CXXSTD: 14,17,latest
CXXSTD: 20,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin;
+8
View File
@@ -0,0 +1,8 @@
# Copyright 2020, 2025 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
project : default-build release <link>static <cxxstd>17
: requirements <library>/boost/core//boost_core ;
exe sv_find_first_of : sv_find_first_of.cpp ;
exe sv_find_first_not_of : sv_find_first_not_of.cpp ;
+277
View File
@@ -0,0 +1,277 @@
// Copyright 2021, 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/utility/string_view.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/type_name.hpp>
#include <boost/cstdint.hpp>
#include <string_view>
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
template<class Sv> void test()
{
constexpr char const* q1 = "{";
constexpr char const* q2 = "<(";
constexpr char const* q3 = " :=";
constexpr char const* q4 = " \t\r\n";
constexpr char const* q6 = " \t\r\n\f\v";
constexpr char const* q10 = "0123456789";
constexpr char const* q52 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
constexpr std::size_t npos = static_cast<std::size_t>( -1 );
constexpr std::size_t N = 1'000'000'000;
std::cout << boost::core::type_name<Sv>() << ":\n\n";
auto t0 = std::chrono::steady_clock::now();
{
constexpr char const* q = q1;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q2;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q3;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q4;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q6;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q10;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q52;
std::string s1( 1'000'000, q[ std::strlen( q ) - 1 ] );
std::string s2( 100, q[ std::strlen( q ) - 1 ] );
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_not_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_not_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
auto tn = std::chrono::steady_clock::now();
std::cout << "\nTotal for " << boost::core::type_name<Sv>() << ": " << ( tn - t0 ) / 1ms << " ms\n\n";
}
int main()
{
test<std::string_view>();
test<boost::string_view>();
test<boost::core::string_view>();
return boost::report_errors();
}
+259
View File
@@ -0,0 +1,259 @@
// Copyright 2021, 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/utility/string_view.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/type_name.hpp>
#include <boost/cstdint.hpp>
#include <string_view>
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
template<class Sv> void test()
{
std::string s1( 1'000'000, '\x00' );
std::string s2( 100, '\x00' );
constexpr char const* q1 = "{";
constexpr char const* q2 = "<(";
constexpr char const* q3 = " :=";
constexpr char const* q4 = " \t\r\n";
constexpr char const* q6 = " \t\r\n\f\v";
constexpr char const* q10 = "0123456789";
constexpr char const* q52 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
constexpr std::size_t npos = static_cast<std::size_t>( -1 );
constexpr std::size_t N = 1'000'000'000;
std::cout << boost::core::type_name<Sv>() << ":\n\n";
auto t0 = std::chrono::steady_clock::now();
{
constexpr char const* q = q1;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q2;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q3;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q4;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q6;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q10;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
{
constexpr char const* q = q52;
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s1.size(); ++i )
{
BOOST_TEST_EQ( Sv( s1 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s1.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
{
auto t1 = std::chrono::steady_clock::now();
for( std::size_t i = 0; i < N / s2.size(); ++i )
{
BOOST_TEST_EQ( Sv( s2 ).find_first_of( q ), npos );
}
auto t2 = std::chrono::steady_clock::now();
std::cout << "find_first_of( sv, \"" << q << "\" ) in " << s2.size() << " bytes: " << ( t2 - t1 ) / 1ms << " ms\n";
}
}
auto tn = std::chrono::steady_clock::now();
std::cout << "\nTotal for " << boost::core::type_name<Sv>() << ": " << ( tn - t0 ) / 1ms << " ms\n\n";
}
int main()
{
test<std::string_view>();
test<boost::string_view>();
test<boost::core::string_view>();
return boost::report_errors();
}
+6
View File
@@ -7,6 +7,12 @@
[section Revision History]
[section Changes in 1.91.0]
* The header [link core.is_placeholder `boost/is_placeholder.hpp`] has been moved from Bind to Core. ([github_issue 90])
[endsect]
[section Changes in 1.90.0]
* The implementation of `BOOST_TEST_THROWS` and `BOOST_TEST_NO_THROW` macros defined in
+1
View File
@@ -61,6 +61,7 @@ criteria for inclusion is that the utility component be:
[include functor.qbk]
[include identity.qbk]
[include ignore_unused.qbk]
[include is_placeholder.qbk]
[include is_same.qbk]
[include launder.qbk]
[include lightweight_test.qbk]
+69
View File
@@ -0,0 +1,69 @@
[/
Copyright 2014, 2025 Peter Dimov
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
]
[section:is_placeholder is_placeholder]
[simplesect Authors]
* Peter Dimov
[endsimplesect]
[section Header <boost/is_placeholder.hpp>]
The header `<boost/is_placeholder.hpp>` defines the class template
`boost::is_placeholder<T>`. It defines a nested integral constant
`value` which is `0` when `T` is not a `boost::bind` placeholder
type, and a positive value corresponding to the placeholder index
otherwise.
That is, `is_placeholder<_1>::value` is `1`,
`is_placeholder<_2>::value` is `2`, and so on.
`is_placeholder` can be specialized for user types. If it is,
`boost::bind` will recognize these types as placeholders.
[section Synopsis]
``
namespace boost
{
template<class T> struct is_placeholder;
}
``
[endsect]
[section Example]
``
#include <boost/is_placeholder.hpp>
#include <boost/bind.hpp>
struct arg1_type {};
constexpr arg1_type arg1{};
template<> struct boost::is_placeholder<arg1_type>
{
static constexpr int value = 1;
};
int f( int x ) { return x + 1; }
int main()
{
return boost::bind( f, arg1 )( -1 );
}
``
[endsect]
[endsect]
[endsect]
+1 -1
View File
@@ -18,7 +18,7 @@
The header `<boost/core/null_deleter.hpp>` defines the `boost::null_deleter` function object,
which can be used as a deleter with smart pointers such as `unique_ptr` or `shared_ptr`. The
deleter doesn't do anything with the pointer provided upon deallocation, which makes it useful
when the pointed object is deallocated elsewhere.
when the pointed object doesn't need to be deallocated or is deallocated elsewhere.
[section Example]
``
+17 -10
View File
@@ -156,18 +156,15 @@ inline void no_throw_failed_impl(const char* expr, const char* what, const char*
# pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
// specialize test output for char pointers to avoid printing as cstring
template <class T> inline const T& test_output_impl(const T& v) { return v; }
inline const void* test_output_impl(const char* v) { return v; }
inline const void* test_output_impl(const unsigned char* v) { return v; }
inline const void* test_output_impl(const signed char* v) { return v; }
inline const void* test_output_impl(char* v) { return v; }
inline const void* test_output_impl(unsigned char* v) { return v; }
inline const void* test_output_impl(signed char* v) { return v; }
template<class T> inline const void* test_output_impl(T volatile* v) { return const_cast<T*>(v); }
// specialize test output for pointers to avoid printing as cstring
template<class T> inline T const& test_output_impl( T const& v ) { return v; }
template<class T> inline void const* test_output_impl( T* const& v ) { return v; }
template<class T> inline void const* test_output_impl( T volatile* const& v ) { return const_cast<T*>(v); }
#if !defined( BOOST_NO_CXX11_NULLPTR )
inline const void* test_output_impl(std::nullptr_t) { return nullptr; }
inline const void* test_output_impl( std::nullptr_t ) { return nullptr; }
#endif
// print chars as numeric
@@ -210,6 +207,16 @@ inline std::string test_output_impl( char const& v )
}
}
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
inline std::string test_output_impl( char8_t const& v )
{
// assume that char is ASCII, compatible with char8_t
return test_output_impl( static_cast<char>( v ) );
}
#endif
// predicates
struct lw_test_eq
+8 -2
View File
@@ -23,9 +23,15 @@ class span;
namespace detail {
template<class U, class T>
template<class U, class T, class = void>
struct span_convertible {
static constexpr bool value = std::is_convertible<U(*)[], T(*)[]>::value;
static constexpr bool value = false;
};
template<class U, class T>
struct span_convertible<U, T, typename
std::enable_if<std::is_convertible<U(*)[], T(*)[]>::value>::type> {
static constexpr bool value = true;
};
template<std::size_t E, std::size_t N>
+31
View File
@@ -0,0 +1,31 @@
#ifndef BOOST_IS_PLACEHOLDER_HPP_INCLUDED
#define BOOST_IS_PLACEHOLDER_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined( _MSC_VER ) && ( _MSC_VER >= 1020 )
# pragma once
#endif
// is_placeholder.hpp - TR1 is_placeholder metafunction
//
// Copyright (c) 2006 Peter Dimov
//
// 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
namespace boost
{
template< class T > struct is_placeholder
{
enum _vt { value = 0 };
};
} // namespace boost
#endif // #ifndef BOOST_IS_PLACEHOLDER_HPP_INCLUDED
+1 -1
View File
@@ -6,7 +6,7 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(HAVE_BOOST_TEST)
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::static_assert Boost::type_traits)
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::core Boost::config Boost::type_traits)
set(BOOST_TEST_LINK_LIBRARIES Boost::core Boost::throw_exception)
+4 -1
View File
@@ -14,7 +14,7 @@ import testing ;
project : requirements
<library>/boost/core//boost_core
<library>/boost/static_assert//boost_static_assert
<library>/boost/config//boost_config
<library>/boost/type_traits//boost_type_traits
<warnings>extra
<toolset>msvc:<warnings-as-errors>on
@@ -177,6 +177,9 @@ run lightweight_test_with_test.cpp
: : : $(pedantic-errors) ;
run-fail lightweight_test_with_fail.cpp ;
run lightweight_test_eq_ptr.cpp
: : : $(pedantic-errors) ;
run is_same_test.cpp ;
run typeinfo_test.cpp ;
+106
View File
@@ -0,0 +1,106 @@
// Copyright 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
int main()
{
{
char const* p = "12";
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
{
wchar_t const* p = L"12";
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
#if !defined( BOOST_NO_CXX11_CHAR16_T )
{
char16_t const* p = u"12";
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
#endif
#if !defined( BOOST_NO_CXX11_CHAR32_T )
{
char32_t const* p = U"12";
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
#endif
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
{
char8_t const* p = u8"12";
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
#endif
{
int v;
int volatile* p = &v;
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
{
int v;
int const volatile* p = &v;
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
{
char v;
char volatile* p = &v;
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
{
char v;
char const volatile* p = &v;
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
{
wchar_t v;
wchar_t volatile* p = &v;
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
{
wchar_t v;
wchar_t const volatile* p = &v;
BOOST_TEST_EQ( p, p );
BOOST_TEST_NE( p, p + 1 );
}
return boost::report_errors();
}
+10 -1
View File
@@ -1,6 +1,6 @@
// Test BOOST_TEST_EQ with character types
//
// Copyright 2020 Peter Dimov
// Copyright 2020, 2025 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -19,14 +19,23 @@ int main()
#if !defined(BOOST_NO_CXX11_CHAR16_T)
BOOST_TEST_EQ( u'A', u'A' );
BOOST_TEST_EQ( (char16_t)1, (char16_t)1 );
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
BOOST_TEST_EQ( U'A', U'A' );
BOOST_TEST_EQ( (char32_t)1, (char32_t)1 );
#endif
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
BOOST_TEST_EQ( u8'A', u8'A' );
BOOST_TEST_EQ( (char8_t)1, (char8_t)1 );
#endif
return boost::report_errors();
+18
View File
@@ -25,6 +25,20 @@ struct range {
}
};
struct buffer {
void* data() {
return 0;
}
const void* data() const {
return 0;
}
std::size_t size() const {
return 0;
}
};
struct base { };
struct derived
@@ -138,6 +152,10 @@ void test_range()
const range<int>&>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<boost::span<base>,
range<derived>&>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<boost::span<int>,
buffer>));
BOOST_TEST_TRAIT_FALSE((std::is_constructible<boost::span<int>,
const buffer&>));
}
void test_initializer_list()