2
0
mirror of https://github.com/boostorg/compat.git synced 2026-01-21 04:42:38 +00:00

5 Commits

Author SHA1 Message Date
Peter Dimov
e7098ce569 Bump MSVC < 1950 workarounds to < 1960; still unfixed. Sad! 2026-01-20 18:51:03 +02:00
Peter Dimov
96ec9c1b89 Add msvc-14.5 to .drone.jsonnet 2026-01-20 18:44:56 +02:00
Christian Mazakas
945b2862b4 invoke internal storage via reference
This prevents the code from erroneously copying the storage which causes
surprising behavior as noted here:
https://github.com/boostorg/compat/issues/23
2026-01-20 07:30:53 -08:00
Christian Mazakas
fbad5e0834 add test for in-place mutation of SBO-stored callables 2026-01-20 07:30:25 -08:00
Peter Dimov
7ce75ac955 Update ci.yml 2026-01-16 02:16:52 +02:00
8 changed files with 59 additions and 18 deletions

View File

@@ -292,4 +292,10 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
"cppalliance/dronevs2022:1", "cppalliance/dronevs2022:1",
{ TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' }, { TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' },
), ),
windows_pipeline(
"Windows VS2026 msvc-14.5",
"cppalliance/dronevs2026:1",
{ TOOLSET: 'msvc-14.5', CXXSTD: '14,17,20,latest' },
),
] ]

View File

@@ -183,18 +183,24 @@ jobs:
- toolset: clang - toolset: clang
compiler: clang++-20 compiler: clang++-20
cxxstd: "03,11,14,17,20,23,2c" cxxstd: "03,11,14,17,20,23,2c"
container: ubuntu:25.04 container: ubuntu:24.04
os: ubuntu-latest os: ubuntu-latest
install: clang-20 install: clang-20
- toolset: clang - toolset: clang
cxxstd: "03,11,14,17,20,2b" compiler: clang++-21
os: macos-13 cxxstd: "03,11,14,17,20,23,2c"
container: ubuntu:25.10
os: ubuntu-latest
install: clang-21
- toolset: clang - toolset: clang
cxxstd: "03,11,14,17,20,2b" cxxstd: "03,11,14,17,20,2b"
os: macos-14 os: macos-14
- toolset: clang - toolset: clang
cxxstd: "03,11,14,17,20,2b" cxxstd: "03,11,14,17,20,23,2c"
os: macos-15 os: macos-15
- toolset: clang
cxxstd: "03,11,14,17,20,23,2c"
os: macos-26
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@@ -321,9 +327,9 @@ jobs:
include: include:
- os: ubuntu-22.04 - os: ubuntu-22.04
- os: ubuntu-24.04 - os: ubuntu-24.04
- os: macos-13
- os: macos-14 - os: macos-14
- os: macos-15 - os: macos-15
- os: macos-26
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@@ -370,9 +376,9 @@ jobs:
include: include:
- os: ubuntu-22.04 - os: ubuntu-22.04
- os: ubuntu-24.04 - os: ubuntu-24.04
- os: macos-13
- os: macos-14 - os: macos-14
- os: macos-15 - os: macos-15
- os: macos-26
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
@@ -429,9 +435,9 @@ jobs:
include: include:
- os: ubuntu-22.04 - os: ubuntu-22.04
- os: ubuntu-24.04 - os: ubuntu-24.04
- os: macos-13
- os: macos-14 - os: macos-14
- os: macos-15 - os: macos-15
- os: macos-26
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}

View File

@@ -247,7 +247,7 @@ bool is_nullary_arg( F f )
template<bool NoEx, class R, class ...Args> template<bool NoEx, class R, class ...Args>
struct mo_invoke_function_holder struct mo_invoke_function_holder
{ {
static R invoke_function( storage s, Args&&... args) noexcept( NoEx ) static R invoke_function( storage const& s, Args&&... args) noexcept( NoEx )
{ {
auto f = reinterpret_cast<R(*)( Args... )>( s.pfn_ ); auto f = reinterpret_cast<R(*)( Args... )>( s.pfn_ );
return compat::invoke_r<R>( f, std::forward<Args>( args )... ); return compat::invoke_r<R>( f, std::forward<Args>( args )... );
@@ -257,7 +257,7 @@ struct mo_invoke_function_holder
template<ref_quals RQ, bool Const, bool NoEx, class F, class R, class ...Args> template<ref_quals RQ, bool Const, bool NoEx, class F, class R, class ...Args>
struct mo_invoke_object_holder struct mo_invoke_object_holder
{ {
static R invoke_object( storage s, Args&&... args ) noexcept( NoEx ) static R invoke_object( storage const& s, Args&&... args ) noexcept( NoEx )
{ {
using T = remove_reference_t<F>; using T = remove_reference_t<F>;
using cv_T = conditional_t<Const, add_const_t<T>, T>; using cv_T = conditional_t<Const, add_const_t<T>, T>;
@@ -274,7 +274,7 @@ struct mo_invoke_object_holder
template<ref_quals RQ, bool Const, bool NoEx, class F, class R, class ...Args> template<ref_quals RQ, bool Const, bool NoEx, class F, class R, class ...Args>
struct mo_invoke_local_holder struct mo_invoke_local_holder
{ {
static R invoke_local( storage s, Args&&... args ) noexcept( NoEx ) static R invoke_local( storage const& s, Args&&... args ) noexcept( NoEx )
{ {
using T = remove_reference_t<F>; using T = remove_reference_t<F>;
using cv_T = conditional_t<Const, add_const_t<T>, T>; using cv_T = conditional_t<Const, add_const_t<T>, T>;
@@ -285,7 +285,7 @@ struct mo_invoke_local_holder
> >
>; >;
return compat::invoke_r<R>( static_cast<cv_ref_T>( *static_cast<cv_T*>( s.addr() ) ), std::forward<Args>( args )... ); return compat::invoke_r<R>( static_cast<cv_ref_T>( *static_cast<cv_T*>( const_cast<storage&>( s ).addr() ) ), std::forward<Args>( args )... );
} }
}; };
@@ -485,9 +485,9 @@ struct move_only_function_base
detail::storage s_; detail::storage s_;
#if defined(__cpp_noexcept_function_type) #if defined(__cpp_noexcept_function_type)
R ( *invoke_ )( detail::storage, Args&&... ) noexcept( NoEx ) = nullptr; R ( *invoke_ )( detail::storage const&, Args&&... ) noexcept( NoEx ) = nullptr;
#else #else
R ( *invoke_ )( detail::storage, Args&&... ) = nullptr; R ( *invoke_ )( detail::storage const&, Args&&... ) = nullptr;
#endif #endif
void ( *manager_ )( op_type, detail::storage&, detail::storage* ) = &manage_empty; void ( *manager_ )( op_type, detail::storage&, detail::storage* ) = &manage_empty;
}; };

View File

@@ -39,7 +39,7 @@ int main()
BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &x )(), -1 ); BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &x )(), -1 );
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950) #if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1960)
{ {
BOOST_TEST_EQ( boost::compat::bind_back( &X::m, Y() )(), -1 ); BOOST_TEST_EQ( boost::compat::bind_back( &X::m, Y() )(), -1 );

View File

@@ -39,7 +39,7 @@ int main()
BOOST_TEST_EQ( boost::compat::bind_front( &X::m, &x )(), -1 ); BOOST_TEST_EQ( boost::compat::bind_front( &X::m, &x )(), -1 );
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950) #if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1960)
{ {
BOOST_TEST_EQ( boost::compat::bind_front( &X::m, Y() )(), -1 ); BOOST_TEST_EQ( boost::compat::bind_front( &X::m, Y() )(), -1 );

View File

@@ -29,7 +29,7 @@ int main()
BOOST_TEST_EQ( boost::compat::invoke( &X::m, &x ), -1 ); BOOST_TEST_EQ( boost::compat::invoke( &X::m, &x ), -1 );
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950) #if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1960)
{ {
BOOST_TEST_EQ( boost::compat::invoke( &X::m, Y() ), -1 ); BOOST_TEST_EQ( boost::compat::invoke( &X::m, Y() ), -1 );

View File

@@ -36,7 +36,7 @@ int main()
#endif #endif
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950) #if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1960)
{ {
constexpr Y y = {}; constexpr Y y = {};

View File

@@ -13,7 +13,8 @@
#include <boost/core/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp> #include <boost/core/lightweight_test_trait.hpp>
#include <functional> #include <array>
#include <cstdint>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
@@ -845,11 +846,39 @@ static void test_conv()
} }
} }
static void test_mutable_lambda()
{
{
// Within SBO limits.
int captured = 0;
move_only_function<int()> func = [captured]() mutable { return ++captured; };
BOOST_TEST_EQ( func(), 1 );
BOOST_TEST_EQ( func(), 2 );
move_only_function<int()> func2(std::move(func));
BOOST_TEST_EQ( func2(), 3 );
}
{
// Too large for SBO.
std::array<std::uint8_t, 256> captured = {{}};
move_only_function<int()> func = [captured]() mutable { return ++captured[0]; };
BOOST_TEST_EQ( func(), 1 );
BOOST_TEST_EQ( func(), 2 );
move_only_function<int()> func2(std::move(func));
BOOST_TEST_EQ( func2(), 3 );
}
}
int main() int main()
{ {
test_call(); test_call();
test_traits(); test_traits();
test_conv(); test_conv();
test_mutable_lambda();
return boost::report_errors(); return boost::report_errors();
} }