// Copyright 2024 Christian Mazakas // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #include #include #include 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 fv1(f); BOOST_TEST_EQ(fv1(), -1); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&&>)); compat::function_ref fv2(f); int x = 1; BOOST_TEST_EQ(fv2(x), 1); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&>)); compat::function_ref fv3(f); BOOST_TEST_EQ(fv3(1, 2), 12); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&&>)); compat::function_ref fv4(f); BOOST_TEST_EQ(fv4(1, 2, 3), 123); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, 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, F1>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1&&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1&&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1 const&&>)); compat::function_ref fv3(f); BOOST_TEST_EQ(fv3(1, 2), 12); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&&>)); compat::function_ref fv4(f); BOOST_TEST_EQ(fv4(1, 2, 3), 123); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1&&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1 const&&>)); } { using S1 = int(); using S2 = int(int); auto& fref = f; compat::function_ref fv1(fref); BOOST_TEST_EQ(fv1(), -1); compat::function_ref fv2(fref); BOOST_TEST_EQ(fv2(1), 1); } { using S1 = int(); using S2 = int(int); compat::function_ref fv1(std::move(f)); BOOST_TEST_EQ(fv1(), -1); compat::function_ref 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 fv3(fref); BOOST_TEST_EQ(fv3(1, 2), 12); compat::function_ref 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 fv3(fref); BOOST_TEST_EQ(fv3(1, 2), 12); compat::function_ref fv4(fref); BOOST_TEST_EQ(fv4(1, 2, 3), 123); } } { F2 g; { compat::function_ref fv1(g); BOOST_TEST_EQ(fv1(3, 2), 321); auto& gref = g; compat::function_ref rfv1(gref); BOOST_TEST_EQ(rfv1(3, 2), 321); compat::function_ref fv2(std::move(g)); BOOST_TEST_EQ(fv2(3, 2), 321); compat::function_ref fv3(g); BOOST_TEST_EQ(fv3(3, 2), 322); auto const& gcref = g; compat::function_ref crfv3(gcref); BOOST_TEST_EQ(fv3(3, 2), 322); compat::function_ref fv4(std::move(g)); BOOST_TEST_EQ(fv4(3, 2), 322); } } // invoke_r { F1 f; compat::function_ref fv1(f); BOOST_TEST_EQ(fv1(1, 2, 3).v, 123); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1>)); compat::function_ref fv2(f); BOOST_TEST_EQ(fv2(1, 2, 3).v, 123); BOOST_TEST_TRAIT_FALSE((std::is_constructible, F1>)); BOOST_TEST_TRAIT_TRUE((std::is_constructible, F1>)); compat::function_ref fv3(f); fv3(1, 2, 3); compat::function_ref fv4(f); fv4(1, 2, 3); } // copy construct, copy assign { F1 f; auto id = [] { return 7331; }; compat::function_ref fv(f); compat::function_ref fv2(fv); BOOST_TEST_EQ(fv(), fv2()); fv2 = compat::function_ref(id); BOOST_TEST_EQ(fv2(), 7331); auto add = [](int x, int y) { return x + y; }; compat::function_ref cfv(f); compat::function_ref cfv2(cfv); BOOST_TEST_EQ(cfv(1, 2), cfv2(1, 2)); cfv2 = compat::function_ref(add); BOOST_TEST_EQ(cfv2(1, 2), 3); } return boost::report_errors(); }