mirror of
https://github.com/boostorg/compat.git
synced 2026-01-19 04:02:16 +00:00
Sync from upstream.
This commit is contained in:
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -54,8 +54,7 @@ jobs:
|
||||
install: g++-10
|
||||
- toolset: gcc-11
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-11
|
||||
os: ubuntu-22.04
|
||||
- toolset: gcc-12
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: ubuntu-22.04
|
||||
@@ -159,9 +158,6 @@ jobs:
|
||||
container: ubuntu:24.04
|
||||
os: ubuntu-latest
|
||||
install: clang-18
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-11
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: macos-12
|
||||
@@ -293,9 +289,9 @@ jobs:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
- os: macos-14
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
@@ -342,9 +338,9 @@ jobs:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
- os: macos-14
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
@@ -401,9 +397,9 @@ jobs:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
- os: macos-12
|
||||
- os: macos-13
|
||||
- os: macos-14
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
|
||||
@@ -52,6 +52,9 @@ class function_ref<R(ArgTypes...) cv noexcept(noex)> {
|
||||
public:
|
||||
template<class F> function_ref(F*) noexcept;
|
||||
template<class F> function_ref(F&&) noexcept;
|
||||
template<auto f> function_ref(nontype_t<f>) noexcept;
|
||||
template<auto f, class U> function_ref(nontype_t<f>, U&&) noexcept;
|
||||
template<auto f, class T> function_ref(nontype_t<f>, cv T*) noexcept;
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
@@ -92,6 +95,76 @@ participates in resolution when `fn` is not a pointer-to-member or pointer-to-me
|
||||
+
|
||||
Calling the `function_ref` is expression-equivalent to: + `invoke_r<R>(static_cast<cv T&>(f), call-args...)`.
|
||||
|
||||
### Pointer to Member Function Constructor
|
||||
|
||||
```cpp
|
||||
template<auto f> function_ref(nontype_t<f>) noexcept;
|
||||
```
|
||||
|
||||
[horizontal]
|
||||
Effects:;; Constructs a `function_ref` using the supplied pointer to member function. This overload only participates
|
||||
in resolution when `f` is a pointer to member or pointer to member function. +
|
||||
+
|
||||
Calling the `function_ref` is express-equivalent to: `invoke_r<R>(f, class-args)`.
|
||||
Example:;;
|
||||
+
|
||||
--
|
||||
```cpp
|
||||
struct point { int x = 1, y = 2; };
|
||||
|
||||
point p;
|
||||
compat::function_ref<int(point const&)> f(compat::nontype_t<&point::x>{});
|
||||
|
||||
BOOST_TEST_EQ(f(p), 1);
|
||||
```
|
||||
--
|
||||
|
||||
### Bound Object Constructor
|
||||
|
||||
```cpp
|
||||
template<auto f, class U> function_ref(nontype_t<f>, U&&) noexcept;
|
||||
```
|
||||
|
||||
[horizontal]
|
||||
Effects:;; Constructs a `function_ref` using the supplied pointer to member or pointer to member function and a reference
|
||||
to an object to bind it to. +
|
||||
+
|
||||
This overload only participates in resolution if `is_rvalue_reference_v<U&&>` is false.
|
||||
Example:;;
|
||||
+
|
||||
--
|
||||
```cpp
|
||||
struct point { int x = 1, y = 2; };
|
||||
|
||||
point p;
|
||||
compat::function_ref<int()> f(compat::nontype_t<&point::x>{}, p);
|
||||
|
||||
BOOST_TEST_EQ(f(), 1);
|
||||
```
|
||||
--
|
||||
|
||||
### Bound Pointer Constructor
|
||||
|
||||
```cpp
|
||||
template<auto f, class T> function_ref(nontype_t<f>, cv T*) noexcept;
|
||||
```
|
||||
|
||||
[horizontal]
|
||||
Effects:;; Constructs a `function_ref` using the supplied pointer to member or pointer to member function and a pointer
|
||||
to an object.
|
||||
Example:;;
|
||||
+
|
||||
--
|
||||
```cpp
|
||||
struct point { int x = 1, y = 2; };
|
||||
|
||||
point p;
|
||||
compat::function_ref<int()> f(compat::nontype_t<&point::x>{}, &p);
|
||||
|
||||
BOOST_TEST_EQ(f(), 1);
|
||||
```
|
||||
--
|
||||
|
||||
### Copy Constructor
|
||||
|
||||
```cpp
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
#include <boost/compat/invoke.hpp>
|
||||
#include <boost/compat/type_traits.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L
|
||||
#define BOOST_COMPAT_HAS_AUTO_NTTP
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace compat {
|
||||
@@ -18,6 +21,15 @@ namespace compat {
|
||||
template <class... S>
|
||||
struct function_ref;
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto V>
|
||||
struct nontype_t {
|
||||
explicit nontype_t() = default;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <bool NoEx>
|
||||
@@ -43,6 +55,34 @@ struct invoke_object_holder {
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto f, bool Const, bool NoEx, class R, class... Args>
|
||||
struct invoke_mem_fn_holder {
|
||||
static R invoke_mem_fn(thunk_storage<NoEx> /* s */, Args&&... args) noexcept(NoEx) {
|
||||
return compat::invoke_r<R>(f, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <auto f, class U, bool Const, bool NoEx, class R, class... Args>
|
||||
struct invoke_target_mem_fn_holder {
|
||||
static R invoke_mem_fn(thunk_storage<NoEx> s, Args&&... args) noexcept(NoEx) {
|
||||
using T = remove_reference_t<U>;
|
||||
using cv_T = conditional_t<Const, add_const_t<T>, T>;
|
||||
return compat::invoke_r<R>(f, *static_cast<cv_T*>(s.pobj_), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <auto f, class T, bool Const, bool NoEx, class R, class... Args>
|
||||
struct invoke_ptr_mem_fn_holder {
|
||||
static R invoke_mem_fn(thunk_storage<NoEx> s, Args&&... args) noexcept(NoEx) {
|
||||
using cv_T = conditional_t<Const, add_const_t<T>, T>;
|
||||
return compat::invoke_r<R>(f, static_cast<cv_T*>(s.pobj_), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <bool Const, bool NoEx, class R, class... Args>
|
||||
struct function_ref_base {
|
||||
private:
|
||||
@@ -52,6 +92,7 @@ private:
|
||||
public:
|
||||
struct fp_tag {};
|
||||
struct obj_tag {};
|
||||
struct mem_fn_tag {};
|
||||
|
||||
template <class F>
|
||||
function_ref_base(fp_tag, F* fn) noexcept
|
||||
@@ -62,9 +103,31 @@ public:
|
||||
template <class F>
|
||||
function_ref_base(obj_tag, F&& fn) noexcept
|
||||
: thunk_{}, invoke_(&invoke_object_holder<Const, NoEx, F, R, Args...>::invoke_object) {
|
||||
thunk_.pobj_ = static_cast<void*>(std::addressof(fn));
|
||||
thunk_.pobj_ = const_cast<void*>(static_cast<void const*>(std::addressof(fn)));
|
||||
}
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto f, class F = decltype(f)>
|
||||
function_ref_base(mem_fn_tag, nontype_t<f>)
|
||||
: thunk_{}, invoke_(&invoke_mem_fn_holder<F{f}, Const, NoEx, R, Args...>::invoke_mem_fn) {
|
||||
thunk_.pobj_ = nullptr;
|
||||
}
|
||||
|
||||
template <auto f, class U, class F = decltype(f)>
|
||||
function_ref_base(mem_fn_tag, nontype_t<f>, U&& obj)
|
||||
: thunk_{}, invoke_(&invoke_target_mem_fn_holder<F{f}, U, Const, NoEx, R, Args...>::invoke_mem_fn) {
|
||||
thunk_.pobj_ = const_cast<void*>(static_cast<void const*>(std::addressof(obj)));
|
||||
}
|
||||
|
||||
template <auto f, class T, class F = decltype(f)>
|
||||
function_ref_base(mem_fn_tag, nontype_t<f>, T* obj)
|
||||
: thunk_{}, invoke_(&invoke_ptr_mem_fn_holder<F{f}, T, Const, NoEx, R, Args...>::invoke_mem_fn) {
|
||||
thunk_.pobj_ = const_cast<void*>(static_cast<void const*>(obj));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
function_ref_base(const function_ref_base&) noexcept = default;
|
||||
function_ref_base& operator=(const function_ref_base&) noexcept = default;
|
||||
|
||||
@@ -78,6 +141,7 @@ struct function_ref<R(Args...)> : public detail::function_ref_base<false, false,
|
||||
private:
|
||||
using base_type = detail::function_ref_base<false, false, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::mem_fn_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
@@ -93,6 +157,20 @@ public:
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto f, class F = decltype(f), enable_if_t<is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x) noexcept : base_type(mem_fn_tag{}, x) {}
|
||||
|
||||
template <auto f, class U, class T = remove_reference_t<U>, class F = decltype(f),
|
||||
enable_if_t<!std::is_rvalue_reference_v<U&&> && is_invocable_using<F, T&>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, U&& obj) noexcept : base_type(mem_fn_tag{}, x, std::forward<U>(obj)) {}
|
||||
|
||||
template <auto f, class T, class F = decltype(f), enable_if_t<is_invocable_using<F, T*>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, T* obj) noexcept : base_type(mem_fn_tag{}, x, obj) {}
|
||||
|
||||
#endif
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
@@ -105,6 +183,7 @@ struct function_ref<R(Args...) const> : public detail::function_ref_base<true, f
|
||||
private:
|
||||
using base_type = detail::function_ref_base<true, false, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::mem_fn_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
@@ -120,6 +199,20 @@ public:
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto f, class F = decltype(f), enable_if_t<is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x) noexcept : base_type(mem_fn_tag{}, x) {}
|
||||
|
||||
template <auto f, class U, class T = remove_reference_t<U>, class F = decltype(f),
|
||||
enable_if_t<!std::is_rvalue_reference_v<U&&> && is_invocable_using<F, T const&>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, U&& obj) noexcept : base_type(mem_fn_tag{}, x, std::forward<U>(obj)) {}
|
||||
|
||||
template <auto f, class T, class F = decltype(f), enable_if_t<is_invocable_using<F, T const*>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, T const* obj) noexcept : base_type(mem_fn_tag{}, x, obj) {}
|
||||
|
||||
#endif
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
@@ -134,6 +227,7 @@ struct function_ref<R(Args...) noexcept> : public detail::function_ref_base<fals
|
||||
private:
|
||||
using base_type = detail::function_ref_base<false, true, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::mem_fn_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
@@ -149,6 +243,20 @@ public:
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto f, class F = decltype(f), enable_if_t<is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x) noexcept : base_type(mem_fn_tag{}, x) {}
|
||||
|
||||
template <auto f, class U, class T = remove_reference_t<U>, class F = decltype(f),
|
||||
enable_if_t<!std::is_rvalue_reference_v<U&&> && is_invocable_using<F, T&>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, U&& obj) noexcept : base_type(mem_fn_tag{}, x, std::forward<U>(obj)) {}
|
||||
|
||||
template <auto f, class T, class F = decltype(f), enable_if_t<is_invocable_using<F, T*>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, T* obj) noexcept : base_type(mem_fn_tag{}, x, obj) {}
|
||||
|
||||
#endif
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
@@ -161,6 +269,7 @@ struct function_ref<R(Args...) const noexcept> : public detail::function_ref_bas
|
||||
private:
|
||||
using base_type = detail::function_ref_base<true, true, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::mem_fn_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
@@ -176,6 +285,20 @@ public:
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
#if defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
|
||||
template <auto f, class F = decltype(f), enable_if_t<is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x) noexcept : base_type(mem_fn_tag{}, x) {}
|
||||
|
||||
template <auto f, class U, class T = remove_reference_t<U>, class F = decltype(f),
|
||||
enable_if_t<!std::is_rvalue_reference_v<U&&> && is_invocable_using<F, T const&>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, U&& obj) noexcept : base_type(mem_fn_tag{}, x, std::forward<U>(obj)) {}
|
||||
|
||||
template <auto f, class T, class F = decltype(f), enable_if_t<is_invocable_using<F, T const*>::value, int> = 0>
|
||||
function_ref(nontype_t<f> x, T const* obj) noexcept : base_type(mem_fn_tag{}, x, obj) {}
|
||||
|
||||
#endif
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
|
||||
@@ -107,6 +107,8 @@ run is_nothrow_invocable_r_test.cpp ;
|
||||
|
||||
run function_ref_fn_test.cpp ;
|
||||
run function_ref_obj_test.cpp ;
|
||||
run function_ref_mfn_test.cpp ;
|
||||
|
||||
run function_ref_fn_noexcept_test.cpp ;
|
||||
run function_ref_mfn_noexcept_test.cpp ;
|
||||
run function_ref_obj_noexcept_test.cpp ;
|
||||
|
||||
@@ -39,7 +39,7 @@ int main()
|
||||
BOOST_TEST_EQ( boost::compat::bind_back( &X::m, &x )(), -1 );
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1940)
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950)
|
||||
|
||||
{
|
||||
BOOST_TEST_EQ( boost::compat::bind_back( &X::m, Y() )(), -1 );
|
||||
|
||||
@@ -39,7 +39,7 @@ int main()
|
||||
BOOST_TEST_EQ( boost::compat::bind_front( &X::m, &x )(), -1 );
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1940)
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950)
|
||||
|
||||
{
|
||||
BOOST_TEST_EQ( boost::compat::bind_front( &X::m, Y() )(), -1 );
|
||||
|
||||
164
test/function_ref_mfn_noexcept_test.cpp
Normal file
164
test/function_ref_mfn_noexcept_test.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright 2024 Christian Mazakas
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 7
|
||||
#pragma GCC diagnostic ignored "-Wnoexcept-type"
|
||||
#endif
|
||||
|
||||
#include <boost/compat/function_ref.hpp>
|
||||
|
||||
#if !defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("no support for placeholder NTTPs detected, skipping this test")
|
||||
int main() {}
|
||||
#else
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
struct F1 {
|
||||
std::unique_ptr<int> p_;
|
||||
|
||||
F1() : p_(new int(1)) {}
|
||||
|
||||
int m1() { return *p_ + -1; }
|
||||
int m2(int x1) noexcept { return 10 * *p_ + x1; }
|
||||
int m3(int x1, int x2) const { return 100 * *p_ + 10 * x1 + x2; }
|
||||
int m4(int x1, int x2, int x3) const noexcept { return 1000 * *p_ + 100 * x1 + 10 * x2 + x3; }
|
||||
};
|
||||
|
||||
namespace compat = boost::compat;
|
||||
|
||||
int main() {
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1&) noexcept>, compat::nontype_t<&F1::m1>>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(F1&, int) noexcept>, compat::nontype_t<&F1::m2>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1&, int, int) noexcept>, compat::nontype_t<&F1::m3>>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(F1&, int, int, int) noexcept>, compat::nontype_t<&F1::m4>>));
|
||||
}
|
||||
|
||||
{
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(F1&, int) noexcept> fn2(compat::nontype_t<&F1::m2>{});
|
||||
BOOST_TEST_EQ(fn2(f1, 2), 12);
|
||||
|
||||
compat::function_ref<int(F1&, int, int, int) noexcept> fn4(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f1, 2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1&) const noexcept>, compat::nontype_t<&F1::m1>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1&, int, int) const noexcept>, compat::nontype_t<&F1::m3>>));
|
||||
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(F1&, int) const noexcept> fn2(compat::nontype_t<&F1::m2>{});
|
||||
BOOST_TEST_EQ(fn2(f1, 2), 12);
|
||||
|
||||
compat::function_ref<int(F1&, int, int, int) const noexcept> fn4(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f1, 2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1 const&) noexcept>, compat::nontype_t<&F1::m1>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1 const&, int) noexcept>, compat::nontype_t<&F1::m2>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1 const&, int, int) noexcept>, compat::nontype_t<&F1::m3>>));
|
||||
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(F1 const&, int, int, int) noexcept> fn4(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f1, 2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int() noexcept>, compat::nontype_t<&F1::m1>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(int) noexcept>, compat::nontype_t<&F1::m2>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int) noexcept>, compat::nontype_t<&F1::m3>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int, int) noexcept>, compat::nontype_t<&F1::m4>, F1&>));
|
||||
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(int) noexcept> fn2(compat::nontype_t<&F1::m2>{}, f1);
|
||||
BOOST_TEST_EQ(fn2(2), 12);
|
||||
|
||||
compat::function_ref<int(int, int, int) noexcept> fn4(compat::nontype_t<&F1::m4>{}, f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int() const noexcept>, compat::nontype_t<&F1::m1>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int) const noexcept>, compat::nontype_t<&F1::m2>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(int, int) const noexcept>,
|
||||
compat::nontype_t<&F1::m3>, F1 const&>));
|
||||
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(int, int, int) const noexcept> fn4(compat::nontype_t<&F1::m4>{}, f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
|
||||
auto const& f1_2 = f1;
|
||||
compat::function_ref<int(int, int, int) const noexcept> fn4_2(compat::nontype_t<&F1::m4>{}, f1_2);
|
||||
BOOST_TEST_EQ(fn4_2(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int() noexcept>, compat::nontype_t<&F1::m1>, F1*>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(int) noexcept>, compat::nontype_t<&F1::m2>, F1*>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int) noexcept>, compat::nontype_t<&F1::m3>, F1*>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int, int) noexcept>, compat::nontype_t<&F1::m4>, F1*>));
|
||||
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(int) noexcept> fn2(compat::nontype_t<&F1::m2>{}, &f1);
|
||||
BOOST_TEST_EQ(fn2(2), 12);
|
||||
|
||||
compat::function_ref<int(int, int, int) noexcept> fn4(compat::nontype_t<&F1::m4>{}, &f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int() const noexcept>, compat::nontype_t<&F1::m1>, F1 const*>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int) const noexcept>, compat::nontype_t<&F1::m2>, F1 const*>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(int, int) const noexcept>,
|
||||
compat::nontype_t<&F1::m3>, F1 const*>));
|
||||
|
||||
F1 const f1;
|
||||
|
||||
compat::function_ref<int(int, int, int) const noexcept> fn4(compat::nontype_t<&F1::m4>{}, &f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
|
||||
auto const& f1_2 = f1;
|
||||
compat::function_ref<int(int, int, int) const noexcept> fn4_2(compat::nontype_t<&F1::m4>{}, &f1_2);
|
||||
BOOST_TEST_EQ(fn4_2(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
176
test/function_ref_mfn_test.cpp
Normal file
176
test/function_ref_mfn_test.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2024 Christian Mazakas
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 7
|
||||
#pragma GCC diagnostic ignored "-Wnoexcept-type"
|
||||
#endif
|
||||
|
||||
#include <boost/compat/function_ref.hpp>
|
||||
|
||||
#if !defined(BOOST_COMPAT_HAS_AUTO_NTTP)
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
BOOST_PRAGMA_MESSAGE("no support for placeholder NTTPs detected, skipping this test")
|
||||
int main() {}
|
||||
#else
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
struct F1 {
|
||||
std::unique_ptr<int> p_;
|
||||
int q_ = 1337;
|
||||
|
||||
F1() : p_(new int(1)) {}
|
||||
|
||||
int m1() { return *p_ + -1; }
|
||||
int m2(int x1) noexcept { return 10 * *p_ + x1; }
|
||||
int m3(int x1, int x2) const { return 100 * *p_ + 10 * x1 + x2; }
|
||||
int m4(int x1, int x2, int x3) const noexcept { return 1000 * *p_ + 100 * x1 + 10 * x2 + x3; }
|
||||
};
|
||||
|
||||
namespace compat = boost::compat;
|
||||
|
||||
int main() {
|
||||
{
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(F1&)> fn1(compat::nontype_t<&F1::m1>{});
|
||||
BOOST_TEST_EQ(fn1(f1), 0);
|
||||
|
||||
compat::function_ref<int(F1&, int)> fn2(compat::nontype_t<&F1::m2>{});
|
||||
BOOST_TEST_EQ(fn2(f1, 2), 12);
|
||||
|
||||
compat::function_ref<int(F1&, int, int)> fn3(compat::nontype_t<&F1::m3>{});
|
||||
BOOST_TEST_EQ(fn3(f1, 2, 3), 123);
|
||||
|
||||
compat::function_ref<int(F1&, int, int, int)> fn4(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f1, 2, 3, 4), 1234);
|
||||
|
||||
compat::function_ref<int(F1&)> a1(compat::nontype_t<&F1::q_>{});
|
||||
BOOST_TEST_EQ(a1(f1), 1337);
|
||||
}
|
||||
|
||||
{
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(F1&) const> fn1(compat::nontype_t<&F1::m1>{});
|
||||
BOOST_TEST_EQ(fn1(f1), 0);
|
||||
|
||||
compat::function_ref<int(F1&, int) const> fn2(compat::nontype_t<&F1::m2>{});
|
||||
BOOST_TEST_EQ(fn2(f1, 2), 12);
|
||||
|
||||
compat::function_ref<int(F1&, int, int) const> fn3(compat::nontype_t<&F1::m3>{});
|
||||
BOOST_TEST_EQ(fn3(f1, 2, 3), 123);
|
||||
|
||||
compat::function_ref<int(F1&, int, int, int) const> fn4(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f1, 2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(F1 const&)>, compat::nontype_t<&F1::m1>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(F1 const&, int)>, compat::nontype_t<&F1::m2>>));
|
||||
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int(F1 const&, int, int) const> fn3(compat::nontype_t<&F1::m3>{});
|
||||
BOOST_TEST_EQ(fn3(f1, 2, 3), 123);
|
||||
|
||||
compat::function_ref<int(F1 const&, int, int, int) const> fn4(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f1, 2, 3, 4), 1234);
|
||||
|
||||
auto const& f2 = f1;
|
||||
|
||||
compat::function_ref<int(F1 const&, int, int) const> fn23(compat::nontype_t<&F1::m3>{});
|
||||
BOOST_TEST_EQ(fn3(f2, 2, 3), 123);
|
||||
|
||||
compat::function_ref<int(F1 const&, int, int, int) const> fn24(compat::nontype_t<&F1::m4>{});
|
||||
BOOST_TEST_EQ(fn4(f2, 2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<int(int)>, compat::nontype_t<&F1::m2>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int)>, compat::nontype_t<&F1::m2>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(int)>, compat::nontype_t<&F1::m2>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(int)>, compat::nontype_t<&F1::m2>, F1>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int) const>, compat::nontype_t<&F1::m3>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int) const>, compat::nontype_t<&F1::m3>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int) const>, compat::nontype_t<&F1::m3>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int, int) const>, compat::nontype_t<&F1::m3>, F1>));
|
||||
}
|
||||
|
||||
{
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int()> fn1(compat::nontype_t<&F1::m1>{}, f1);
|
||||
BOOST_TEST_EQ(fn1(), 0);
|
||||
|
||||
compat::function_ref<int(int)> fn2(compat::nontype_t<&F1::m2>{}, f1);
|
||||
BOOST_TEST_EQ(fn2(2), 12);
|
||||
|
||||
compat::function_ref<int(int, int)> fn3(compat::nontype_t<&F1::m3>{}, f1);
|
||||
BOOST_TEST_EQ(fn3(2, 3), 123);
|
||||
|
||||
compat::function_ref<int(int, int, int)> fn4(compat::nontype_t<&F1::m4>{}, f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
F1 const f1;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int() const>, compat::nontype_t<&F1::m1>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int) const>, compat::nontype_t<&F1::m2>, F1&>));
|
||||
|
||||
compat::function_ref<int(int, int) const> fn3(compat::nontype_t<&F1::m3>{}, f1);
|
||||
BOOST_TEST_EQ(fn3(2, 3), 123);
|
||||
|
||||
compat::function_ref<int(int, int, int) const> fn4(compat::nontype_t<&F1::m4>{}, f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
F1 f1;
|
||||
|
||||
compat::function_ref<int()> fn1(compat::nontype_t<&F1::m1>{}, &f1);
|
||||
BOOST_TEST_EQ(fn1(), 0);
|
||||
|
||||
compat::function_ref<int(int)> fn2(compat::nontype_t<&F1::m2>{}, &f1);
|
||||
BOOST_TEST_EQ(fn2(2), 12);
|
||||
|
||||
compat::function_ref<int(int, int)> fn3(compat::nontype_t<&F1::m3>{}, &f1);
|
||||
BOOST_TEST_EQ(fn3(2, 3), 123);
|
||||
|
||||
compat::function_ref<int(int, int, int)> fn4(compat::nontype_t<&F1::m4>{}, &f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
{
|
||||
F1 const f1;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int() const>, compat::nontype_t<&F1::m1>, F1 const*>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(int) const>, compat::nontype_t<&F1::m2>, F1 const*>));
|
||||
|
||||
compat::function_ref<int(int, int) const> fn3(compat::nontype_t<&F1::m3>{}, &f1);
|
||||
BOOST_TEST_EQ(fn3(2, 3), 123);
|
||||
|
||||
compat::function_ref<int(int, int, int) const> fn4(compat::nontype_t<&F1::m4>{}, &f1);
|
||||
BOOST_TEST_EQ(fn4(2, 3, 4), 1234);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -67,25 +67,36 @@ int main() {
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S2> fv2(f1);
|
||||
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S4> fv4(f1);
|
||||
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&&>));
|
||||
}
|
||||
{
|
||||
using S1 = int() const noexcept;
|
||||
@@ -95,25 +106,57 @@ int main() {
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S3>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S4> fv4(f1);
|
||||
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&&>));
|
||||
}
|
||||
|
||||
{
|
||||
using S2 = int(int) noexcept;
|
||||
using S4 = int(int, int, int) noexcept;
|
||||
|
||||
auto& fref = f1;
|
||||
|
||||
compat::function_ref<S2> fv2(fref);
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
|
||||
auto const& cfref = f1;
|
||||
compat::function_ref<S4> fv4(cfref);
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
}
|
||||
|
||||
{
|
||||
using S4 = int(int, int, int) const noexcept;
|
||||
|
||||
auto const& cfref = f1;
|
||||
compat::function_ref<S4> fv4(cfref);
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,13 +166,17 @@ int main() {
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F2>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F2&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F2&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F2 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F2 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F2 const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F2>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F2&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F2&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F2 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F2 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F2 const&&>));
|
||||
}
|
||||
|
||||
// invoke_r
|
||||
|
||||
@@ -59,30 +59,39 @@ int main() {
|
||||
compat::function_ref<S1> fv1(f);
|
||||
|
||||
BOOST_TEST_EQ(fv1(), -1);
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S2> fv2(f);
|
||||
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&>));
|
||||
|
||||
compat::function_ref<S3> fv3(f);
|
||||
|
||||
BOOST_TEST_EQ(fv3(1, 2), 12);
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S4> fv4(f);
|
||||
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&&>));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -93,29 +102,89 @@ int main() {
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S1>, F1 const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<S2>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S3> fv3(f);
|
||||
|
||||
BOOST_TEST_EQ(fv3(1, 2), 12);
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S3>, F1 const&&>));
|
||||
|
||||
compat::function_ref<S4> fv4(f);
|
||||
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&&>));
|
||||
}
|
||||
|
||||
{
|
||||
using S1 = int();
|
||||
using S2 = int(int);
|
||||
|
||||
auto& fref = f;
|
||||
|
||||
compat::function_ref<S1> fv1(fref);
|
||||
BOOST_TEST_EQ(fv1(), -1);
|
||||
|
||||
compat::function_ref<S2> fv2(fref);
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
}
|
||||
|
||||
{
|
||||
using S1 = int();
|
||||
using S2 = int(int);
|
||||
|
||||
compat::function_ref<S1> fv1(std::move(f));
|
||||
BOOST_TEST_EQ(fv1(), -1);
|
||||
|
||||
compat::function_ref<S2> fv2(std::move(f));
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
}
|
||||
|
||||
{
|
||||
using S3 = int(int, int) const;
|
||||
using S4 = int(int, int, int) const;
|
||||
|
||||
auto const& fref = f;
|
||||
|
||||
compat::function_ref<S3> fv3(fref);
|
||||
BOOST_TEST_EQ(fv3(1, 2), 12);
|
||||
|
||||
compat::function_ref<S4> fv4(fref);
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
}
|
||||
|
||||
{
|
||||
using S3 = int(int, int) const;
|
||||
using S4 = int(int, int, int) const;
|
||||
|
||||
auto const&& fref = std::move(f);
|
||||
|
||||
compat::function_ref<S3> fv3(fref);
|
||||
BOOST_TEST_EQ(fv3(1, 2), 12);
|
||||
|
||||
compat::function_ref<S4> fv4(fref);
|
||||
BOOST_TEST_EQ(fv4(1, 2, 3), 123);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,12 +194,20 @@ int main() {
|
||||
compat::function_ref<int(int, int)> fv1(g);
|
||||
BOOST_TEST_EQ(fv1(3, 2), 321);
|
||||
|
||||
auto& gref = g;
|
||||
compat::function_ref<int(int, int)> rfv1(gref);
|
||||
BOOST_TEST_EQ(rfv1(3, 2), 321);
|
||||
|
||||
compat::function_ref<int(int, int)> fv2(std::move(g));
|
||||
BOOST_TEST_EQ(fv2(3, 2), 321);
|
||||
|
||||
compat::function_ref<int(int, int) const> fv3(g);
|
||||
BOOST_TEST_EQ(fv3(3, 2), 322);
|
||||
|
||||
auto const& gcref = g;
|
||||
compat::function_ref<int(int, int) const> crfv3(gcref);
|
||||
BOOST_TEST_EQ(fv3(3, 2), 322);
|
||||
|
||||
compat::function_ref<int(int, int) const> fv4(std::move(g));
|
||||
BOOST_TEST_EQ(fv4(3, 2), 322);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ int main()
|
||||
BOOST_TEST_EQ( boost::compat::invoke( &X::m, &x ), -1 );
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1940)
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950)
|
||||
{
|
||||
BOOST_TEST_EQ( boost::compat::invoke( &X::m, Y() ), -1 );
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ int main()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1940)
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, >= 1920 && BOOST_MSVC < 1950)
|
||||
{
|
||||
constexpr Y y = {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user