mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
added takes_arg_as_const_reference.hpp and tests
This commit is contained in:
@ -0,0 +1,171 @@
|
||||
/* Copyright 2023 Joaquin M Lopez Munoz.
|
||||
* 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)
|
||||
*
|
||||
* See https://www.boost.org/libs/unordered for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_FOA_TAKES_ARG_AS_CONST_REFERENCE_HPP
|
||||
#define BOOST_UNORDERED_DETAIL_FOA_TAKES_ARG_AS_CONST_REFERENCE_HPP
|
||||
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
/* VS warns when a pp function is directly called with an empty arg */
|
||||
#define BOOST_UNORDERED_EMPTY_PP_ARG()
|
||||
|
||||
namespace boost{
|
||||
namespace unordered{
|
||||
namespace detail{
|
||||
namespace foa{
|
||||
|
||||
template<typename Sig>
|
||||
struct remove_noexcept{using type=Sig;};
|
||||
|
||||
template<typename Sig>
|
||||
using remove_noexcept_t=typename remove_noexcept<Sig>::type;
|
||||
|
||||
template<typename R,typename... Args>
|
||||
struct remove_noexcept<R(Args...)noexcept>
|
||||
{using type=R(Args...);};
|
||||
|
||||
template<typename R,typename... Args>
|
||||
struct remove_noexcept<R(Args...,...)noexcept>
|
||||
{using type=R(Args...,...);};
|
||||
|
||||
template<typename R,typename... Args>
|
||||
struct remove_noexcept<R(&)(Args...)noexcept>
|
||||
{using type=R(&)(Args...);};
|
||||
|
||||
template<typename R,typename... Args>
|
||||
struct remove_noexcept<R(&)(Args...,...)noexcept>
|
||||
{using type=R(&)(Args...,...);};
|
||||
|
||||
template<typename R,typename... Args>
|
||||
struct remove_noexcept<R(*)(Args...)noexcept>
|
||||
{using type=R(Args...);};
|
||||
|
||||
template<typename R,typename... Args>
|
||||
struct remove_noexcept<R(*)(Args...,...)noexcept>
|
||||
{using type=R(Args...,...);};
|
||||
|
||||
#define BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(qualifier) \
|
||||
template<typename R,typename C,typename... Args> \
|
||||
struct remove_noexcept<R(C::*)(Args...)qualifier noexcept> \
|
||||
{using type=R(C::*)(Args...)qualifier;}; \
|
||||
\
|
||||
template<typename R,typename C,typename... Args> \
|
||||
struct remove_noexcept<R(C::*)(Args...,...)qualifier noexcept> \
|
||||
{using type=R(C::*)(Args...,...)qualifier;};
|
||||
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(BOOST_UNORDERED_EMPTY_PP_ARG())
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(const)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(volatile)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(const volatile)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(const&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(volatile&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(const volatile&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(&&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(const&&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(volatile&&)
|
||||
BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN(const volatile&&)
|
||||
|
||||
#undef BOOST_UNORDERED_REMOVE_NOEXCEPT_MEMFUN
|
||||
|
||||
template<typename Sig>
|
||||
struct has_const_reference_arg:std::false_type{};
|
||||
|
||||
template<typename R,typename Arg,typename... Args>
|
||||
struct has_const_reference_arg<
|
||||
R(const Arg&,Args...)
|
||||
>:std::true_type{};
|
||||
|
||||
template<typename R,typename Arg,typename... Args>
|
||||
struct has_const_reference_arg<
|
||||
R(const Arg&,Args...,...)
|
||||
>:std::true_type{};
|
||||
|
||||
template<typename R,typename Arg,typename... Args>
|
||||
struct has_const_reference_arg<
|
||||
R(&)(const Arg&,Args...)
|
||||
>:std::true_type{};
|
||||
|
||||
template<typename R,typename Arg,typename... Args>
|
||||
struct has_const_reference_arg<
|
||||
R(&)(const Arg&,Args...,...)
|
||||
>:std::true_type{};
|
||||
|
||||
template<typename R,typename Arg,typename... Args>
|
||||
struct has_const_reference_arg<
|
||||
R(*)(const Arg&,Args...)
|
||||
>:std::true_type{};
|
||||
|
||||
template<typename R,typename Arg,typename... Args>
|
||||
struct has_const_reference_arg<
|
||||
R(*)(const Arg&,Args...,...)
|
||||
>:std::true_type{};
|
||||
|
||||
#define BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(qualifier) \
|
||||
template<typename R,typename C,typename Arg,typename... Args> \
|
||||
struct has_const_reference_arg< \
|
||||
R(C::*)(const Arg&,Args...)qualifier \
|
||||
>:std::true_type{}; \
|
||||
\
|
||||
template<typename R,typename C,typename Arg,typename... Args> \
|
||||
struct has_const_reference_arg< \
|
||||
R(C::*)(const Arg&,Args...,...)qualifier \
|
||||
>:std::true_type{};
|
||||
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(BOOST_UNORDERED_EMPTY_PP_ARG())
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(volatile)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(volatile&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(&&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const&&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(volatile&&)
|
||||
BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile&&)
|
||||
|
||||
#undef BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN
|
||||
|
||||
/* Detects if f(x) takes x as a const reference. From an implementation
|
||||
* technique by Kenneth Gorking.
|
||||
* Requires: F is invocable with an Arg&.
|
||||
*/
|
||||
|
||||
template<typename F,typename /*Arg*/,typename=void>
|
||||
struct takes_arg_as_const_reference:
|
||||
has_const_reference_arg<remove_noexcept_t<F>>{};
|
||||
|
||||
template<typename F,typename Arg>
|
||||
struct takes_arg_as_const_reference<
|
||||
F,Arg,
|
||||
boost::void_t<decltype(&F::template operator()<Arg>)>
|
||||
>:
|
||||
takes_arg_as_const_reference<
|
||||
decltype(&F::template operator()<Arg>),Arg
|
||||
>{};
|
||||
|
||||
template<typename F,typename Arg>
|
||||
struct takes_arg_as_const_reference<
|
||||
F,Arg,
|
||||
boost::void_t<decltype(&F::operator())>
|
||||
>:
|
||||
takes_arg_as_const_reference<
|
||||
decltype(&F::operator()),Arg
|
||||
>{};
|
||||
|
||||
|
||||
} /* namespace foa */
|
||||
} /* namespace detail */
|
||||
} /* namespace unordered */
|
||||
} /* namespace boost */
|
||||
|
||||
#undef BOOST_UNORDERED_EMPTY_PP_ARG
|
||||
|
||||
#endif
|
@ -202,6 +202,7 @@ local CFOA_TESTS =
|
||||
rw_spinlock_test6
|
||||
rw_spinlock_test7
|
||||
rw_spinlock_test8
|
||||
takes_arg_as_cref_tests
|
||||
;
|
||||
|
||||
for local test in $(CFOA_TESTS)
|
||||
|
177
test/cfoa/takes_arg_as_cref_tests.cpp
Normal file
177
test/cfoa/takes_arg_as_cref_tests.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
// Copyright 2023 Joaquin M Lopez Munoz
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/unordered/detail/foa/takes_arg_as_const_reference.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
using boost::unordered::detail::foa::takes_arg_as_const_reference;
|
||||
|
||||
using f1 = void ( const int& );
|
||||
using f2 = void ( const int& ) noexcept;
|
||||
using f3 = void ( const int&, char* );
|
||||
using f4 = void ( const int&, ... );
|
||||
using f5 = void ( int& );
|
||||
using f6 = void ( int& ) noexcept;
|
||||
using f7 = void ( int&, char* );
|
||||
using f8 = void ( int&, ... );
|
||||
struct f9 { void operator()( const int& ); };
|
||||
struct f10 { void operator()( const int& ) const; };
|
||||
struct f11 { void operator()( const int& ) volatile; };
|
||||
struct f12 { void operator()( const int& ) const volatile; };
|
||||
struct f13 { void operator()( const int& )&; };
|
||||
struct f14 { void operator()( const int& ) const&; };
|
||||
struct f15 { void operator()( const int& ) volatile&; };
|
||||
struct f16 { void operator()( const int& ) const volatile&; };
|
||||
struct f17 { void operator()( const int& )&&; };
|
||||
struct f18 { void operator()( const int& ) const&&; };
|
||||
struct f19 { void operator()( const int& ) volatile&&; };
|
||||
struct f20 { void operator()( const int& ) const volatile&&; };
|
||||
struct f21 { void operator()( const int& ) noexcept; };
|
||||
struct f22 { void operator()( const int& ) const noexcept; };
|
||||
struct f23 { void operator()( const int&, int=0 ); };
|
||||
struct f24 { void operator()( const int&, ... ) noexcept; };
|
||||
struct f25 { void operator()( int& ); };
|
||||
struct f26 { void operator()( int& ) const; };
|
||||
struct f27 { void operator()( int& ) volatile; };
|
||||
struct f28 { void operator()( int& ) const volatile; };
|
||||
struct f29 { void operator()( int& )&; };
|
||||
struct f30 { void operator()( int& ) const&; };
|
||||
struct f31 { void operator()( int& ) volatile&; };
|
||||
struct f32 { void operator()( int& ) const volatile&; };
|
||||
struct f33 { void operator()( int& )&&; };
|
||||
struct f34 { void operator()( int& ) const&&; };
|
||||
struct f35 { void operator()( int& ) volatile&&; };
|
||||
struct f36 { void operator()( int& ) const volatile&&; };
|
||||
struct f37 { void operator()( int& ) noexcept; };
|
||||
struct f38 { void operator()( int& ) const noexcept; };
|
||||
struct f39 { void operator()( int&, int=0 ); };
|
||||
struct f40 { void operator()( int&, ... ) noexcept; };
|
||||
struct f41 { template<typename Arg> void operator()( const Arg& ); };
|
||||
struct f42 { template<typename Arg> void operator()( const Arg& ) const; };
|
||||
struct f43 { template<typename Arg> void operator()( const Arg& ) const noexcept; };
|
||||
struct f44 { template<typename Arg> void operator()( Arg& ); };
|
||||
struct f45 { template<typename Arg> void operator()( Arg& ) const; };
|
||||
struct f46 { template<typename Arg> void operator()( Arg& ) const noexcept; };
|
||||
struct f47 { template<typename Arg> void operator()( Arg ); };
|
||||
struct f48 { template<typename Arg> void operator()( Arg ) const; };
|
||||
struct f49 { template<typename Arg> void operator()( Arg ) const noexcept; };
|
||||
struct f50 // expected false negative
|
||||
{
|
||||
void operator()( const int& );
|
||||
template<typename Arg> void operator()( Arg& );
|
||||
};
|
||||
struct f51 // expected false negative
|
||||
{
|
||||
void operator()( const int& );
|
||||
void operator()( char* );
|
||||
};
|
||||
auto lambda52 = []( const int& ){};
|
||||
using f52=decltype(lambda52);
|
||||
int retrieved=0;
|
||||
auto lambda53 = [&]( const int& x ) mutable { retrieved = x; };
|
||||
using f53=decltype(lambda53);
|
||||
auto lambda54 = []( int& ){};
|
||||
using f54=decltype(lambda54);
|
||||
auto lambda55 = [&]( int& x ) mutable { retrieved = x; };
|
||||
using f55=decltype(lambda55);
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
auto lambda56 = []( const auto& ){};
|
||||
using f56=decltype(lambda56);
|
||||
auto lambda57 = [&]( const int& x ) mutable { retrieved = x; };
|
||||
using f57=decltype(lambda57);
|
||||
auto lambda58 = []( int& ){};
|
||||
using f58=decltype(lambda58);
|
||||
auto lambda59 = [&]( int& x ) mutable { retrieved = x; };
|
||||
using f59=decltype(lambda59);
|
||||
#endif
|
||||
|
||||
using f60=void; // detection doesn't crash even if requirements violated
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f1, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f2, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f3, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f4, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f5, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f6, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f7, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f8, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f1*, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f2*, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f3*, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f4*, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f5*, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f6*, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f7*, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f8*, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f1&, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f2&, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f3&, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f4&, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f5&, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f6&, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f7&, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f8&, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f9, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f10, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f11, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f12, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f13, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f14, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f15, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f16, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f17, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f18, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f19, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f20, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f21, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f22, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f23, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f24, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f25, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f26, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f27, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f28, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f29, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f30, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f31, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f32, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f33, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f34, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f35, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f36, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f37, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f38, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f39, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f40, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f41, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f42, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f43, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f44, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f45, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f46, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f47, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f48, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f49, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f50, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f51, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f52, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f53, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f54, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f55, int>::value ));
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_GENERIC_LAMBDAS)
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f56, int>::value ));
|
||||
BOOST_TEST(( takes_arg_as_const_reference<f57, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f58, int>::value ));
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f59, int>::value ));
|
||||
#endif
|
||||
|
||||
BOOST_TEST(( !takes_arg_as_const_reference<f60, int>::value ));
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
Reference in New Issue
Block a user