mirror of
https://github.com/boostorg/compat.git
synced 2026-01-19 04:02:16 +00:00
Add initial draft of function_ref
This commit is contained in:
185
include/boost/compat/function_ref.hpp
Normal file
185
include/boost/compat/function_ref.hpp
Normal file
@@ -0,0 +1,185 @@
|
||||
#ifndef BOOST_COMPAT_FUNCTION_REF_HPP_INCLUDED
|
||||
#define BOOST_COMPAT_FUNCTION_REF_HPP_INCLUDED
|
||||
|
||||
// Copyright 2024 Christian Mazakas.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/compat/invoke.hpp>
|
||||
#include <boost/compat/type_traits.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace compat {
|
||||
|
||||
template <class... S>
|
||||
struct function_ref;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <bool NoEx>
|
||||
union thunk_storage {
|
||||
void* pobj_;
|
||||
void (*pfn_)() noexcept(NoEx);
|
||||
};
|
||||
|
||||
template <bool NoEx, class Fp, class R, class... Args>
|
||||
R invoke_function(thunk_storage<NoEx> s, Args&&... args) noexcept(NoEx) {
|
||||
auto f = reinterpret_cast<Fp>(s.pfn_);
|
||||
return compat::invoke_r<R>(f, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <bool Const, bool NoEx, class F, class R, class... Args>
|
||||
R invoke_object(thunk_storage<NoEx> s, Args&&... args) noexcept(NoEx) {
|
||||
using T = remove_reference_t<F>;
|
||||
using cv_T = conditional_t<Const, add_const_t<T>, T>;
|
||||
return compat::invoke_r<R>(*static_cast<cv_T*>(s.pobj_), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <bool Const, bool NoEx, class R, class... Args>
|
||||
struct function_ref_base {
|
||||
private:
|
||||
thunk_storage<NoEx> thunk_ = nullptr;
|
||||
R (*invoke_)(thunk_storage<NoEx>, Args&&...) noexcept(NoEx) = nullptr;
|
||||
|
||||
public:
|
||||
struct fp_tag {};
|
||||
struct obj_tag {};
|
||||
|
||||
template <class F>
|
||||
function_ref_base(fp_tag, F* fn) noexcept : thunk_{}, invoke_(&invoke_function<NoEx, F*, R, Args...>) {
|
||||
thunk_.pfn_ = reinterpret_cast<decltype(thunk_.pfn_)>(fn);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
function_ref_base(obj_tag, F&& fn) noexcept : thunk_{}, invoke_(&invoke_object<Const, NoEx, F, R, Args...>) {
|
||||
thunk_.pobj_ = static_cast<void*>(std::addressof(fn));
|
||||
}
|
||||
|
||||
function_ref_base(const function_ref_base&) noexcept = default;
|
||||
function_ref_base& operator=(const function_ref_base&) noexcept = default;
|
||||
|
||||
R operator()(Args&&... args) const noexcept(NoEx) { return this->invoke_(thunk_, std::forward<Args>(args)...); }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class R, class... Args>
|
||||
struct function_ref<R(Args...)> : public detail::function_ref_base<false, false, R, Args...> {
|
||||
private:
|
||||
using base_type = detail::function_ref_base<false, false, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
using is_invocable_using = boost::compat::is_invocable_r<R, T..., Args...>;
|
||||
|
||||
public:
|
||||
template <class F, enable_if_t<std::is_function<F>::value && is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(F* fn) noexcept : base_type(fp_tag{}, fn) {}
|
||||
|
||||
template <class F, class T = remove_reference_t<F>,
|
||||
enable_if_t<!std::is_same<remove_cvref_t<F>, function_ref>::value && !std::is_member_pointer<T>::value &&
|
||||
is_invocable_using<T&>::value,
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
template <class T, enable_if_t<!std::is_same<T, function_ref>::value && !std::is_pointer<T>::value, int> = 0>
|
||||
function_ref& operator=(T) = delete;
|
||||
};
|
||||
|
||||
template <class R, class... Args>
|
||||
struct function_ref<R(Args...) const> : public detail::function_ref_base<true, false, R, Args...> {
|
||||
private:
|
||||
using base_type = detail::function_ref_base<true, false, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
using is_invocable_using = boost::compat::is_invocable_r<R, T..., Args...>;
|
||||
|
||||
public:
|
||||
template <class F, enable_if_t<std::is_function<F>::value && is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(F* fn) noexcept : base_type(fp_tag{}, fn) {}
|
||||
|
||||
template <class F, class T = remove_reference_t<F>,
|
||||
enable_if_t<!std::is_same<remove_cvref_t<F>, function_ref>::value && !std::is_member_pointer<T>::value &&
|
||||
is_invocable_using<T const&>::value,
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
template <class T, enable_if_t<!std::is_same<T, function_ref>::value && !std::is_pointer<T>::value, int> = 0>
|
||||
function_ref& operator=(T) = delete;
|
||||
};
|
||||
|
||||
#if defined(__cpp_noexcept_function_type)
|
||||
|
||||
template <class R, class... Args>
|
||||
struct function_ref<R(Args...) noexcept> : public detail::function_ref_base<false, true, R, Args...> {
|
||||
private:
|
||||
using base_type = detail::function_ref_base<false, true, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
using is_invocable_using = boost::compat::is_nothrow_invocable_r<R, T..., Args...>;
|
||||
|
||||
public:
|
||||
template <class F, enable_if_t<std::is_function<F>::value && is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(F* fn) noexcept : base_type(fp_tag{}, fn) {}
|
||||
|
||||
template <class F, class T = remove_reference_t<F>,
|
||||
enable_if_t<!std::is_same<remove_cvref_t<F>, function_ref>::value && !std::is_member_pointer<T>::value &&
|
||||
is_invocable_using<T&>::value,
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
template <class T, enable_if_t<!std::is_same<T, function_ref>::value && !std::is_pointer<T>::value, int> = 0>
|
||||
function_ref& operator=(T) = delete;
|
||||
};
|
||||
|
||||
template <class R, class... Args>
|
||||
struct function_ref<R(Args...) const noexcept> : public detail::function_ref_base<true, true, R, Args...> {
|
||||
private:
|
||||
using base_type = detail::function_ref_base<true, true, R, Args...>;
|
||||
using typename base_type::fp_tag;
|
||||
using typename base_type::obj_tag;
|
||||
|
||||
template <class... T>
|
||||
using is_invocable_using = boost::compat::is_nothrow_invocable_r<R, T..., Args...>;
|
||||
|
||||
public:
|
||||
template <class F, enable_if_t<std::is_function<F>::value && is_invocable_using<F>::value, int> = 0>
|
||||
function_ref(F* fn) noexcept : base_type(fp_tag{}, fn) {}
|
||||
|
||||
template <class F, class T = remove_reference_t<F>,
|
||||
enable_if_t<!std::is_same<remove_cvref_t<F>, function_ref>::value && !std::is_member_pointer<T>::value &&
|
||||
is_invocable_using<T const&>::value,
|
||||
int> = 0>
|
||||
function_ref(F&& fn) noexcept : base_type(obj_tag{}, fn) {}
|
||||
|
||||
function_ref(const function_ref&) noexcept = default;
|
||||
function_ref& operator=(const function_ref&) noexcept = default;
|
||||
|
||||
template <class T, enable_if_t<!std::is_same<T, function_ref>::value && !std::is_pointer<T>::value, int> = 0>
|
||||
function_ref& operator=(T) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace compat
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_COMPAT_FUNCTION_REF_HPP_INCLUDED
|
||||
@@ -2,6 +2,7 @@
|
||||
#define BOOST_COMPAT_TYPE_TRAITS_HPP_INCLUDED
|
||||
|
||||
// Copyright 2024 Peter Dimov
|
||||
// Copyright 2024 Christian Mazakas
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
@@ -32,6 +33,8 @@ template<class...> struct make_void
|
||||
|
||||
template<class... T> using void_t = typename detail::make_void<T...>::type;
|
||||
|
||||
template<class T> using add_const_t = typename std::add_const<T>::type;
|
||||
|
||||
} // namespace compat
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -94,3 +94,9 @@ compile invoke_r_md_constexpr_test.cpp
|
||||
|
||||
run is_invocable_r_test.cpp ;
|
||||
run is_nothrow_invocable_r_test.cpp ;
|
||||
|
||||
run function_ref_fn_test.cpp ;
|
||||
run function_ref_obj_test.cpp ;
|
||||
|
||||
run function_ref_fn_noexcept_test.cpp ;
|
||||
run function_ref_obj_noexcept_test.cpp ;
|
||||
|
||||
165
test/function_ref_fn_noexcept_test.cpp
Normal file
165
test/function_ref_fn_noexcept_test.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
// Copyright 2024 Christian Mazakas
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if !defined(__cpp_noexcept_function_type)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Test skipped, __cpp_noexcept_function_type is not defined")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/compat/function_ref.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
int f0() { return -1; }
|
||||
|
||||
int f1(int x1) noexcept { return x1; }
|
||||
int g1(int x1) noexcept { return x1 * 2; }
|
||||
|
||||
int f2(int x1, int x2) { return 10 * x1 + x2; }
|
||||
|
||||
int f3(int x1, int x2, int x3) noexcept { return 100 * x1 + 10 * x2 + x3; }
|
||||
|
||||
int g(std::unique_ptr<int> p, std::unique_ptr<int> q) { return 10 * *p + *q; }
|
||||
|
||||
struct X {
|
||||
int v = 0;
|
||||
|
||||
X() = default;
|
||||
X(int v_) noexcept : v{v_} {}
|
||||
};
|
||||
|
||||
struct Y {
|
||||
int v = 0;
|
||||
|
||||
Y() = default;
|
||||
explicit Y(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
struct Z {
|
||||
int v = 0;
|
||||
|
||||
Z() = default;
|
||||
Z(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
namespace compat = boost::compat;
|
||||
|
||||
int main() {
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int() noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int() const noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int) noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int) const noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int) noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int) const noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int, int) noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int, int) const noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<X(int, int, int) noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<X(int, int, int) const noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<void(int, int, int) noexcept>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<void(int, int, int) const noexcept>>));
|
||||
|
||||
struct W {
|
||||
int w_;
|
||||
};
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int() noexcept>, W>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int() const noexcept>, W>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int() noexcept>, compat::function_ref<int()>>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int()>, compat::function_ref<int() noexcept>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_assignable<compat::function_ref<int() const noexcept>, compat::function_ref<int() const>>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_assignable<compat::function_ref<int() noexcept>, compat::function_ref<int(int) noexcept>>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_assignable<compat::function_ref<int(int) noexcept>, compat::function_ref<int() noexcept>>));
|
||||
|
||||
// f0
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int() noexcept>, decltype(f0)>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int() const noexcept>, decltype(f0)>));
|
||||
}
|
||||
|
||||
// f1
|
||||
{
|
||||
compat::function_ref<int(int) noexcept> fv1(f1);
|
||||
BOOST_TEST_EQ(fv1(1), 1);
|
||||
|
||||
compat::function_ref<int(int) const noexcept> fv2(f1);
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
}
|
||||
|
||||
// f2
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(int, int) noexcept>, decltype(f2)>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<int(int, int) const noexcept>, decltype(f2)>));
|
||||
}
|
||||
|
||||
// f3
|
||||
{
|
||||
compat::function_ref<int(int, int, int) noexcept> fv1(f3);
|
||||
BOOST_TEST_EQ(fv1(1, 2, 3), 123);
|
||||
|
||||
compat::function_ref<int(int, int, int) const noexcept> fv2(f3);
|
||||
BOOST_TEST_EQ(fv2(1, 2, 3), 123);
|
||||
}
|
||||
|
||||
// g
|
||||
{
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(std::unique_ptr<int>, std::unique_ptr<int>) noexcept>,
|
||||
decltype(g)>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<int(std::unique_ptr<int>, std::unique_ptr<int>) const noexcept>,
|
||||
decltype(g)>));
|
||||
}
|
||||
|
||||
// invoke_r
|
||||
{
|
||||
compat::function_ref<X(int, int, int) noexcept> fv1(f3);
|
||||
BOOST_TEST_EQ(fv1(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int) noexcept>, decltype(f3)>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Z(int, int, int) noexcept>, decltype(f3)>));
|
||||
|
||||
compat::function_ref<X(int, int, int) const noexcept> fv2(f3);
|
||||
BOOST_TEST_EQ(fv2(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<Y(int, int, int) const noexcept>, decltype(f3)>));
|
||||
BOOST_TEST_TRAIT_FALSE(
|
||||
(std::is_constructible<compat::function_ref<Z(int, int, int) const noexcept>, decltype(f3)>));
|
||||
|
||||
compat::function_ref<void(int, int, int) noexcept> fv3(f3);
|
||||
fv3(1, 2, 3);
|
||||
|
||||
compat::function_ref<void(int, int, int) const noexcept> fv4(f3);
|
||||
fv4(1, 2, 3);
|
||||
}
|
||||
|
||||
// copy construct, copy assign
|
||||
{
|
||||
compat::function_ref<int(int) noexcept> fv(f1);
|
||||
compat::function_ref<int(int) noexcept> fv2(fv);
|
||||
BOOST_TEST_EQ(fv(42), fv2(42));
|
||||
|
||||
fv2 = g1;
|
||||
BOOST_TEST_EQ(fv2(12), 24);
|
||||
|
||||
compat::function_ref<int(int) const noexcept> cfv(f1);
|
||||
compat::function_ref<int(int) const noexcept> cfv2(cfv);
|
||||
BOOST_TEST_EQ(cfv(42), cfv2(42));
|
||||
|
||||
cfv2 = g1;
|
||||
BOOST_TEST_EQ(cfv2(24), 48);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
183
test/function_ref_fn_test.cpp
Normal file
183
test/function_ref_fn_test.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
// 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>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
int f0() { return -1; }
|
||||
int g0() { return 7331; }
|
||||
|
||||
int f1(int x1) noexcept { return x1; }
|
||||
|
||||
int f2(int x1, int x2) { return 10 * x1 + x2; }
|
||||
|
||||
int f3(int x1, int x2, int x3) noexcept { return 100 * x1 + 10 * x2 + x3; }
|
||||
|
||||
int g(std::unique_ptr<int> p, std::unique_ptr<int> q) { return 10 * *p + *q; }
|
||||
|
||||
struct X {
|
||||
int v = 0;
|
||||
|
||||
X() = default;
|
||||
X(int v_) noexcept : v{v_} {}
|
||||
};
|
||||
|
||||
struct Y {
|
||||
int v = 0;
|
||||
|
||||
Y() = default;
|
||||
explicit Y(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
struct Z {
|
||||
int v = 0;
|
||||
|
||||
Z() = default;
|
||||
Z(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
namespace compat = boost::compat;
|
||||
|
||||
int main() {
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int()>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int() const>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int)>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int) const>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int)>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int) const>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int, int)>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<int(int, int, int) const>>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_trivially_copyable<compat::function_ref<int(std::unique_ptr<int>, std::unique_ptr<int>)>>));
|
||||
BOOST_TEST_TRAIT_TRUE(
|
||||
(std::is_trivially_copyable<compat::function_ref<int(std::unique_ptr<int>, std::unique_ptr<int>) const>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<X(int, int, int)>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<X(int, int, int) const>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<void(int, int, int)>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_trivially_copyable<compat::function_ref<void(int, int, int) const>>));
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
||||
struct W {
|
||||
int w_;
|
||||
};
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int()>, W>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int() const>, W>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int()>, compat::function_ref<int() const>>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int() const>, compat::function_ref<int()>>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int()>, compat::function_ref<int(int)>>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_assignable<compat::function_ref<int(int)>, compat::function_ref<int()>>));
|
||||
#endif
|
||||
|
||||
#else
|
||||
BOOST_PRAGMA_MESSAGE("<type_traits> is incomplete, skipping is_trivially_copyable checks")
|
||||
#endif
|
||||
|
||||
// f0
|
||||
{
|
||||
compat::function_ref<int()> fv1(f0);
|
||||
BOOST_TEST_EQ(fv1(), -1);
|
||||
|
||||
compat::function_ref<int() const> fv2(f0);
|
||||
BOOST_TEST_EQ(fv2(), -1);
|
||||
}
|
||||
|
||||
// f1
|
||||
{
|
||||
compat::function_ref<int(int)> fv1(f1);
|
||||
BOOST_TEST_EQ(fv1(1), 1);
|
||||
|
||||
compat::function_ref<int(int) const> fv2(f1);
|
||||
BOOST_TEST_EQ(fv2(1), 1);
|
||||
}
|
||||
|
||||
// f2
|
||||
{
|
||||
compat::function_ref<int(int, int)> fv1(f2);
|
||||
BOOST_TEST_EQ(fv1(1, 2), 12);
|
||||
|
||||
compat::function_ref<int(int, int) const> fv2(f2);
|
||||
BOOST_TEST_EQ(fv2(1, 2), 12);
|
||||
}
|
||||
|
||||
// f3
|
||||
{
|
||||
compat::function_ref<int(int, int, int)> fv1(f3);
|
||||
BOOST_TEST_EQ(fv1(1, 2, 3), 123);
|
||||
|
||||
compat::function_ref<int(int, int, int) const> fv2(f3);
|
||||
BOOST_TEST_EQ(fv2(1, 2, 3), 123);
|
||||
}
|
||||
|
||||
// g
|
||||
{
|
||||
using S1 = int(std::unique_ptr<int>, std::unique_ptr<int>);
|
||||
using S2 = int(std::unique_ptr<int>, std::unique_ptr<int>) const;
|
||||
|
||||
compat::function_ref<S1> fv1(g);
|
||||
{
|
||||
auto p = std::unique_ptr<int>(new int{1});
|
||||
auto q = std::unique_ptr<int>(new int{2});
|
||||
BOOST_TEST_EQ(fv1(std::move(p), std::move(q)), 12);
|
||||
}
|
||||
|
||||
compat::function_ref<S2> fv2(g);
|
||||
{
|
||||
auto p = std::unique_ptr<int>(new int{130});
|
||||
auto q = std::unique_ptr<int>(new int{37});
|
||||
BOOST_TEST_EQ(fv1(std::move(p), std::move(q)), 1337);
|
||||
}
|
||||
}
|
||||
|
||||
// invoke_r
|
||||
{
|
||||
compat::function_ref<X(int, int, int)> fv1(f3);
|
||||
BOOST_TEST_EQ(fv1(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int)>, decltype(f3)>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<Z(int, int, int)>, decltype(f3)>));
|
||||
|
||||
compat::function_ref<X(int, int, int) const> fv2(f3);
|
||||
BOOST_TEST_EQ(fv2(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int) const>, decltype(f3)>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<Z(int, int, int) const>, decltype(f3)>));
|
||||
|
||||
compat::function_ref<void(int, int, int)> fv3(f3);
|
||||
fv3(1, 2, 3);
|
||||
|
||||
compat::function_ref<void(int, int, int) const> fv4(f3);
|
||||
fv4(1, 2, 3);
|
||||
}
|
||||
|
||||
// copy construct, copy assign
|
||||
{
|
||||
compat::function_ref<int()> fv(f0);
|
||||
compat::function_ref<int()> fv2(fv);
|
||||
BOOST_TEST_EQ(fv(), fv2());
|
||||
|
||||
fv2 = g0;
|
||||
BOOST_TEST_EQ(fv2(), 7331);
|
||||
|
||||
compat::function_ref<int() const> cfv(f0);
|
||||
compat::function_ref<int() const> cfv2(cfv);
|
||||
BOOST_TEST_EQ(cfv(), cfv2());
|
||||
|
||||
cfv2 = g0;
|
||||
BOOST_TEST_EQ(cfv2(), 7331);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
181
test/function_ref_obj_noexcept_test.cpp
Normal file
181
test/function_ref_obj_noexcept_test.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright 2024 Christian Mazakas
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if !defined(__cpp_noexcept_function_type)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Test skipped, __cpp_noexcept_function_type is not defined")
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/compat/function_ref.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
struct F1 {
|
||||
int operator()() { return -1; }
|
||||
|
||||
int operator()(int x1) noexcept { return x1; }
|
||||
|
||||
int operator()(int x1, int x2) const { return 10 * x1 + x2; }
|
||||
|
||||
int operator()(int x1, int x2, int x3) const noexcept { return 100 * x1 + 10 * x2 + x3; }
|
||||
};
|
||||
|
||||
struct F2 {
|
||||
int operator()(int x1, int x2) & { return 100 * x1 + 10 * x2 + 1; }
|
||||
int operator()(int x1, int x2) const& { return 100 * x1 + 10 * x2 + 2; }
|
||||
int operator()(int x1, int x2) && { return 100 * x1 + 10 * x2 + 3; }
|
||||
int operator()(int x1, int x2) const&& { return 100 * x1 + 10 * x2 + 4; }
|
||||
};
|
||||
|
||||
struct X {
|
||||
int v = 0;
|
||||
|
||||
X() = default;
|
||||
X(int v_) noexcept : v{v_} {}
|
||||
};
|
||||
|
||||
struct Y {
|
||||
int v = 0;
|
||||
|
||||
Y() = default;
|
||||
explicit Y(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
struct Z {
|
||||
int v = 0;
|
||||
|
||||
Z() = default;
|
||||
Z(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
namespace compat = boost::compat;
|
||||
|
||||
int main() {
|
||||
{
|
||||
F1 f1;
|
||||
{
|
||||
using S1 = int() noexcept;
|
||||
using S2 = int(int) noexcept;
|
||||
using S3 = int(int, int) noexcept;
|
||||
using S4 = int(int, int, int) noexcept;
|
||||
|
||||
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&>));
|
||||
|
||||
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<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&>));
|
||||
|
||||
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 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
}
|
||||
{
|
||||
using S1 = int() const noexcept;
|
||||
using S2 = int(int) const noexcept;
|
||||
using S3 = int(int, int) const noexcept;
|
||||
using S4 = int(int, int, int) const noexcept;
|
||||
|
||||
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<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<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&>));
|
||||
|
||||
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 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
using S1 = int(int, int) noexcept;
|
||||
using S2 = int(int, int) const noexcept;
|
||||
|
||||
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<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&>));
|
||||
}
|
||||
|
||||
// invoke_r
|
||||
{
|
||||
F1 f;
|
||||
|
||||
compat::function_ref<X(int, int, int) noexcept> fv1(f);
|
||||
BOOST_TEST_EQ(fv1(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int) noexcept>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Z(int, int, int) noexcept>, F1>));
|
||||
|
||||
compat::function_ref<X(int, int, int) const noexcept> fv2(f);
|
||||
BOOST_TEST_EQ(fv2(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int) const noexcept>, F1>));
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Z(int, int, int) const noexcept>, F1>));
|
||||
|
||||
compat::function_ref<void(int, int, int) noexcept> fv3(f);
|
||||
fv3(1, 2, 3);
|
||||
|
||||
compat::function_ref<void(int, int, int) const noexcept> fv4(f);
|
||||
fv4(1, 2, 3);
|
||||
}
|
||||
|
||||
// copy construct, copy assign
|
||||
{
|
||||
F1 f;
|
||||
|
||||
auto id = [](int x) noexcept { return x + 7331; };
|
||||
|
||||
compat::function_ref<int(int) noexcept> fv(f);
|
||||
compat::function_ref<int(int) noexcept> fv2(fv);
|
||||
BOOST_TEST_EQ(fv(12), fv2(12));
|
||||
|
||||
fv2 = compat::function_ref<int(int) noexcept>(id);
|
||||
BOOST_TEST_EQ(fv2(1), 7332);
|
||||
|
||||
auto add = [](int x, int y, int z) noexcept { return x + y + z; };
|
||||
compat::function_ref<int(int, int, int) const noexcept> cfv(f);
|
||||
compat::function_ref<int(int, int, int) const noexcept> cfv2(cfv);
|
||||
BOOST_TEST_EQ(cfv(1, 2, 3), cfv2(1, 2, 3));
|
||||
|
||||
cfv2 = compat::function_ref<int(int, int, int) const noexcept>(add);
|
||||
BOOST_TEST_EQ(cfv2(1, 2, 3), 6);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
183
test/function_ref_obj_test.cpp
Normal file
183
test/function_ref_obj_test.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright 2024 Christian Mazakas
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/compat/function_ref.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
struct F1 {
|
||||
int operator()() { return -1; }
|
||||
|
||||
int operator()(int x1) noexcept { return x1; }
|
||||
|
||||
int operator()(int x1, int x2) const { return 10 * x1 + x2; }
|
||||
|
||||
int operator()(int x1, int x2, int x3) const noexcept { return 100 * x1 + 10 * x2 + x3; }
|
||||
};
|
||||
|
||||
struct F2 {
|
||||
int operator()(int x1, int x2) & { return 100 * x1 + 10 * x2 + 1; }
|
||||
int operator()(int x1, int x2) const& { return 100 * x1 + 10 * x2 + 2; }
|
||||
int operator()(int x1, int x2) && { return 100 * x1 + 10 * x2 + 3; }
|
||||
int operator()(int x1, int x2) const&& { return 100 * x1 + 10 * x2 + 4; }
|
||||
};
|
||||
|
||||
struct X {
|
||||
int v = 0;
|
||||
|
||||
X() = default;
|
||||
X(int v_) noexcept : v{v_} {}
|
||||
};
|
||||
|
||||
struct Y {
|
||||
int v = 0;
|
||||
|
||||
Y() = default;
|
||||
explicit Y(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
struct Z {
|
||||
int v = 0;
|
||||
|
||||
Z() = default;
|
||||
Z(int v_) : v{v_} {}
|
||||
};
|
||||
|
||||
namespace compat = boost::compat;
|
||||
|
||||
int main() {
|
||||
{
|
||||
F1 f;
|
||||
{
|
||||
using S1 = int();
|
||||
using S2 = int(int);
|
||||
using S3 = int(int, int);
|
||||
using S4 = int(int, int, int);
|
||||
|
||||
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&>));
|
||||
|
||||
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 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 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
}
|
||||
|
||||
{
|
||||
using S1 = int() const;
|
||||
using S2 = int(int) const;
|
||||
using S3 = int(int, int) const;
|
||||
using S4 = int(int, int, int) const;
|
||||
|
||||
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<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&>));
|
||||
|
||||
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 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 const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<S4>, F1 const&>));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
F2 g;
|
||||
{
|
||||
compat::function_ref<int(int, int)> fv1(g);
|
||||
BOOST_TEST_EQ(fv1(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);
|
||||
|
||||
compat::function_ref<int(int, int) const> fv4(std::move(g));
|
||||
BOOST_TEST_EQ(fv4(3, 2), 322);
|
||||
}
|
||||
}
|
||||
|
||||
// invoke_r
|
||||
{
|
||||
F1 f;
|
||||
|
||||
compat::function_ref<X(int, int, int)> fv1(f);
|
||||
BOOST_TEST_EQ(fv1(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int)>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<Z(int, int, int)>, F1>));
|
||||
|
||||
compat::function_ref<X(int, int, int) const> fv2(f);
|
||||
BOOST_TEST_EQ(fv2(1, 2, 3).v, 123);
|
||||
BOOST_TEST_TRAIT_FALSE((std::is_constructible<compat::function_ref<Y(int, int, int) const>, F1>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_constructible<compat::function_ref<Z(int, int, int) const>, F1>));
|
||||
|
||||
compat::function_ref<void(int, int, int)> fv3(f);
|
||||
fv3(1, 2, 3);
|
||||
|
||||
compat::function_ref<void(int, int, int) const> fv4(f);
|
||||
fv4(1, 2, 3);
|
||||
}
|
||||
|
||||
// copy construct, copy assign
|
||||
{
|
||||
F1 f;
|
||||
|
||||
auto id = [] { return 7331; };
|
||||
|
||||
compat::function_ref<int()> fv(f);
|
||||
compat::function_ref<int()> fv2(fv);
|
||||
BOOST_TEST_EQ(fv(), fv2());
|
||||
|
||||
fv2 = compat::function_ref<int()>(id);
|
||||
BOOST_TEST_EQ(fv2(), 7331);
|
||||
|
||||
auto add = [](int x, int y) { return x + y; };
|
||||
compat::function_ref<int(int, int) const> cfv(f);
|
||||
compat::function_ref<int(int, int) const> cfv2(cfv);
|
||||
BOOST_TEST_EQ(cfv(1, 2), cfv2(1, 2));
|
||||
|
||||
cfv2 = compat::function_ref<int(int, int) const>(add);
|
||||
BOOST_TEST_EQ(cfv2(1, 2), 3);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user