mirror of
https://github.com/boostorg/core.git
synced 2025-05-10 07:13:54 +00:00
The feader defines a new functor class template that can be used to wrap raw functions into a function object class. This is useful, for example, for integrating std::unique_ptr and unique_resource with custom deleters implemented as raw functions (e.g. in C libraries).
203 lines
5.7 KiB
C++
203 lines
5.7 KiB
C++
/*
|
|
* Copyright Andrey Semashev 2024.
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
|
* http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
/*!
|
|
* \file functor_test.cpp
|
|
* \author Andrey Semashev
|
|
* \date 2024-01-23
|
|
*
|
|
* This file contains tests for \c boost::core::functor.
|
|
*/
|
|
|
|
#include <boost/config.hpp>
|
|
|
|
#if !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
|
|
|
|
#include <boost/core/functor.hpp>
|
|
#include <boost/core/lightweight_test.hpp>
|
|
#include <boost/core/lightweight_test_trait.hpp>
|
|
#include <type_traits>
|
|
|
|
#if (defined(__cpp_lib_is_invocable) && (__cpp_lib_is_invocable >= 201703l)) || \
|
|
(defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION >= 140) && (BOOST_CXX_VERSION >= 201703l))
|
|
|
|
namespace test {
|
|
|
|
using std::is_invocable;
|
|
|
|
} // namespace test
|
|
|
|
#else
|
|
|
|
namespace test {
|
|
|
|
// A simplified implementation that does not support member function pointers
|
|
template< typename Func, typename... Args >
|
|
struct is_invocable_impl
|
|
{
|
|
template< typename F = Func, typename = decltype(std::declval< F >()(std::declval< Args >()...)) >
|
|
static std::true_type _check_invocable(int);
|
|
static std::false_type _check_invocable(...);
|
|
|
|
typedef decltype(is_invocable_impl::_check_invocable(0)) type;
|
|
};
|
|
|
|
template< typename Func, typename... Args >
|
|
struct is_invocable : public is_invocable_impl< Func, Args... >::type { };
|
|
|
|
} // namespace test
|
|
|
|
#endif
|
|
|
|
int g_n = 0;
|
|
|
|
void void_func()
|
|
{
|
|
++g_n;
|
|
}
|
|
|
|
int int_func()
|
|
{
|
|
return ++g_n;
|
|
}
|
|
|
|
int& int_ref_func()
|
|
{
|
|
++g_n;
|
|
return g_n;
|
|
}
|
|
|
|
void void_add1(int x)
|
|
{
|
|
g_n += x;
|
|
}
|
|
|
|
int add2(int x, int y)
|
|
{
|
|
return x + y;
|
|
}
|
|
|
|
namespace test_ns {
|
|
|
|
int add3(int x, int y, int z)
|
|
{
|
|
return x + y + z;
|
|
}
|
|
|
|
} // namespace test_ns
|
|
|
|
int int_func_noexcept() noexcept
|
|
{
|
|
return ++g_n;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
{
|
|
boost::core::functor< void_func > fun;
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_func >& >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_func > const& >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_func > const&, int >));
|
|
BOOST_TEST_EQ(noexcept(fun()), false);
|
|
fun();
|
|
BOOST_TEST_EQ(g_n, 1);
|
|
fun();
|
|
BOOST_TEST_EQ(g_n, 2);
|
|
}
|
|
|
|
g_n = 0;
|
|
{
|
|
boost::core::functor< int_func > fun;
|
|
int res = fun();
|
|
BOOST_TEST_EQ(res, 1);
|
|
BOOST_TEST_EQ(g_n, 1);
|
|
res = fun();
|
|
BOOST_TEST_EQ(res, 2);
|
|
BOOST_TEST_EQ(g_n, 2);
|
|
}
|
|
|
|
g_n = 0;
|
|
{
|
|
boost::core::functor< int_ref_func > fun;
|
|
int& res1 = fun();
|
|
BOOST_TEST_EQ(&res1, &g_n);
|
|
BOOST_TEST_EQ(res1, 1);
|
|
int& res2 = fun();
|
|
BOOST_TEST_EQ(&res2, &g_n);
|
|
BOOST_TEST_EQ(res2, 2);
|
|
}
|
|
|
|
g_n = 0;
|
|
{
|
|
boost::core::functor< void_add1 > fun;
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 >& >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 > const& >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 >&, int >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 > const&, int >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 >&, short int >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< void_add1 > const&, short int >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 > const&, int, int >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< void_add1 > const&, const char* >));
|
|
fun(10);
|
|
BOOST_TEST_EQ(g_n, 10);
|
|
fun(20);
|
|
BOOST_TEST_EQ(g_n, 30);
|
|
}
|
|
|
|
{
|
|
boost::core::functor< add2 > fun;
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 >& >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const& >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 >&, int >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const&, int >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 >&, int, int >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 > const&, int, int >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 >&, short int, signed char >));
|
|
BOOST_TEST_TRAIT_TRUE((test::is_invocable< boost::core::functor< add2 > const&, short int, signed char >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const&, const char* >));
|
|
BOOST_TEST_TRAIT_FALSE((test::is_invocable< boost::core::functor< add2 > const&, const char*, float >));
|
|
int res = fun(10, 20);
|
|
BOOST_TEST_EQ(res, 30);
|
|
res = fun(30, 40);
|
|
BOOST_TEST_EQ(res, 70);
|
|
}
|
|
|
|
{
|
|
boost::core::functor< test_ns::add3 > fun;
|
|
int res = fun(10, 20, 30);
|
|
BOOST_TEST_EQ(res, 60);
|
|
res = fun(40, 50, 60);
|
|
BOOST_TEST_EQ(res, 150);
|
|
}
|
|
|
|
g_n = 0;
|
|
{
|
|
boost::core::functor< int_func_noexcept > fun;
|
|
BOOST_TEST_EQ(noexcept(fun()), true);
|
|
int res = fun();
|
|
BOOST_TEST_EQ(res, 1);
|
|
BOOST_TEST_EQ(g_n, 1);
|
|
res = fun();
|
|
BOOST_TEST_EQ(res, 2);
|
|
BOOST_TEST_EQ(g_n, 2);
|
|
}
|
|
|
|
return boost::report_errors();
|
|
}
|
|
|
|
#else // !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
|
|
|
|
#include <boost/config/pragma_message.hpp>
|
|
|
|
BOOST_PRAGMA_MESSAGE("Test skipped because C++17 auto non-type template parameters are not supported")
|
|
|
|
int main()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif // !defined(BOOST_NO_CXX17_AUTO_NONTYPE_TEMPLATE_PARAMS)
|