mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2024-11-25 00:43:44 +00:00
322 lines
9.6 KiB
C++
322 lines
9.6 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2011-2017 Bolero MURAKAMI
|
|
https://github.com/bolero-MURAKAMI/Sprout
|
|
|
|
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)
|
|
=============================================================================*/
|
|
#ifndef SPROUT_FUNCTIONAL_REF_HPP
|
|
#define SPROUT_FUNCTIONAL_REF_HPP
|
|
|
|
#include <type_traits>
|
|
#include <functional>
|
|
#include <sprout/config.hpp>
|
|
#include <sprout/utility/forward.hpp>
|
|
#include <sprout/type_traits/integral_constant.hpp>
|
|
#include <sprout/type_traits/result_of.hpp>
|
|
#include <sprout/type_traits/identity.hpp>
|
|
#include <sprout/type_traits/has_xxx.hpp>
|
|
#include <sprout/type_traits/inherit_if_xxx.hpp>
|
|
#include <sprout/functional/base.hpp>
|
|
#include <sprout/functional/type_traits/weak_result_type.hpp>
|
|
#include <sprout/functional/type_traits/has_type.hpp>
|
|
#include <sprout/memory/addressof.hpp>
|
|
|
|
namespace sprout {
|
|
// 20.8.3 reference_wrapper
|
|
|
|
namespace detail {
|
|
template<bool Unary, bool Binary, typename T>
|
|
struct reference_wrapper_base_impl;
|
|
template<typename T>
|
|
struct reference_wrapper_base_impl<false, false, T>
|
|
: public sprout::weak_result_type<T>
|
|
{};
|
|
template<typename T>
|
|
struct reference_wrapper_base_impl<true, false, T>
|
|
: public sprout::weak_result_type<T>
|
|
{
|
|
public:
|
|
typedef typename T::argument_type argument_type;
|
|
};
|
|
template<typename T>
|
|
struct reference_wrapper_base_impl<false, true, T>
|
|
: public sprout::weak_result_type<T>
|
|
{
|
|
public:
|
|
typedef typename T::first_argument_type first_argument_type;
|
|
typedef typename T::second_argument_type second_argument_type;
|
|
};
|
|
template<typename T>
|
|
struct reference_wrapper_base_impl<true, true, T>
|
|
: public sprout::weak_result_type<T>
|
|
{
|
|
public:
|
|
typedef typename T::argument_type argument_type;
|
|
typedef typename T::first_argument_type first_argument_type;
|
|
typedef typename T::second_argument_type second_argument_type;
|
|
};
|
|
template<typename T>
|
|
struct reference_wrapper_base
|
|
: public sprout::detail::reference_wrapper_base_impl<
|
|
sprout::has_argument_type<T>::value,
|
|
sprout::has_first_argument_type<T>::value
|
|
&& sprout::has_second_argument_type<T>::value
|
|
,
|
|
T
|
|
>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res(T1)>
|
|
: public sprout::unary_function<T1, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res(T1) const>
|
|
: public sprout::unary_function<T1, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res(T1) volatile>
|
|
: public sprout::unary_function<T1, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res(T1) const volatile>
|
|
: public sprout::unary_function<T1, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res(T1, T2)>
|
|
: public sprout::binary_function<T1, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res(T1, T2) const>
|
|
: public sprout::binary_function<T1, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res(T1, T2) volatile>
|
|
: public sprout::binary_function<T1, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res(T1, T2) const volatile>
|
|
: public sprout::binary_function<T1, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res(*)(T1)>
|
|
: public sprout::unary_function<T1, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res(*)(T1, T2)>
|
|
: public sprout::binary_function<T1, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res (T1::*)()>
|
|
: public sprout::unary_function<T1*, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res (T1::*)(T2)>
|
|
: public sprout::binary_function<T1*, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res (T1::*)() const>
|
|
: public sprout::unary_function<T1 const*, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res (T1::*)(T2) const>
|
|
: public sprout::binary_function<T1 const*, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res (T1::*)() volatile>
|
|
: public sprout::unary_function<T1 volatile*, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res (T1::*)(T2) volatile>
|
|
: public sprout::binary_function<T1 volatile*, T2, Res>
|
|
{};
|
|
template<typename Res, typename T1>
|
|
struct reference_wrapper_base<Res (T1::*)() const volatile>
|
|
: public sprout::unary_function<T1 const volatile*, Res>
|
|
{};
|
|
template<typename Res, typename T1, typename T2>
|
|
struct reference_wrapper_base<Res (T1::*)(T2) const volatile>
|
|
: public sprout::binary_function<T1 const volatile*, T2, Res>
|
|
{};
|
|
} // namespace detail
|
|
|
|
template<typename T>
|
|
class reference_wrapper
|
|
: public sprout::detail::reference_wrapper_base<typename std::remove_cv<T>::type>
|
|
{
|
|
public:
|
|
// types
|
|
typedef T type;
|
|
private:
|
|
T* t_;
|
|
private:
|
|
reference_wrapper(T&&) SPROUT_DELETED_FUNCTION_DECL
|
|
public:
|
|
// construct/copy/destroy
|
|
SPROUT_CONSTEXPR reference_wrapper(T& t) SPROUT_NOEXCEPT
|
|
: t_(sprout::addressof(t))
|
|
{}
|
|
reference_wrapper(reference_wrapper const&) = default;
|
|
// assignment
|
|
SPROUT_CXX14_CONSTEXPR reference_wrapper& operator=(reference_wrapper const& rhs) {
|
|
t_ = rhs.t_;
|
|
return *this;
|
|
}
|
|
// access
|
|
SPROUT_CONSTEXPR operator T& () const SPROUT_NOEXCEPT {
|
|
return *t_;
|
|
}
|
|
SPROUT_CONSTEXPR T& get() const SPROUT_NOEXCEPT {
|
|
return *t_;
|
|
}
|
|
SPROUT_CONSTEXPR T* get_pointer() const SPROUT_NOEXCEPT {
|
|
return t_;
|
|
}
|
|
// invocation
|
|
template<typename... Args>
|
|
SPROUT_CONSTEXPR typename sprout::result_of<T& (Args&&...)>::type
|
|
operator()(Args&&... args) const {
|
|
return (*t_)(SPROUT_FORWARD(Args, args)...);
|
|
}
|
|
};
|
|
|
|
//
|
|
// ref
|
|
// cref
|
|
//
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR sprout::reference_wrapper<T>
|
|
ref(T& t) SPROUT_NOEXCEPT {
|
|
return sprout::reference_wrapper<T>(t);
|
|
}
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR sprout::reference_wrapper<T const>
|
|
cref(T const& t) SPROUT_NOEXCEPT {
|
|
return sprout::reference_wrapper<T const>(t);
|
|
}
|
|
template<typename T>
|
|
void ref(T const&&) SPROUT_DELETED_FUNCTION_DECL
|
|
template<typename T>
|
|
void cref(T const&&) SPROUT_DELETED_FUNCTION_DECL
|
|
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR sprout::reference_wrapper<T>
|
|
ref(sprout::reference_wrapper<T> t) SPROUT_NOEXCEPT {
|
|
return t;
|
|
}
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR sprout::reference_wrapper<T const>
|
|
cref(sprout::reference_wrapper<T> t) SPROUT_NOEXCEPT {
|
|
return sprout::reference_wrapper<T const>(t.get());
|
|
}
|
|
|
|
//
|
|
// is_reference_wrapper
|
|
//
|
|
template<typename T>
|
|
struct is_reference_wrapper
|
|
: public sprout::false_type
|
|
{};
|
|
template<typename T>
|
|
struct is_reference_wrapper<T const>
|
|
: public sprout::is_reference_wrapper<T>
|
|
{};
|
|
template<typename T>
|
|
struct is_reference_wrapper<T volatile>
|
|
: public sprout::is_reference_wrapper<T>
|
|
{};
|
|
template<typename T>
|
|
struct is_reference_wrapper<T const volatile>
|
|
: public sprout::is_reference_wrapper<T>
|
|
{};
|
|
template<typename T>
|
|
struct is_reference_wrapper<sprout::reference_wrapper<T> >
|
|
: public sprout::true_type
|
|
{};
|
|
|
|
//
|
|
// unwrap_reference
|
|
//
|
|
template<typename T>
|
|
struct unwrap_reference
|
|
: public sprout::identity<T>
|
|
{};
|
|
template<typename T>
|
|
struct unwrap_reference<sprout::reference_wrapper<T> >
|
|
: public sprout::identity<T>
|
|
{};
|
|
template<typename T>
|
|
struct unwrap_reference<std::reference_wrapper<T> >
|
|
: public sprout::identity<T>
|
|
{};
|
|
template<typename T>
|
|
struct unwrap_reference<T const>
|
|
: public sprout::unwrap_reference<T>
|
|
{};
|
|
template<typename T>
|
|
struct unwrap_reference<T volatile>
|
|
: public sprout::unwrap_reference<T>
|
|
{};
|
|
template<typename T>
|
|
struct unwrap_reference<T const volatile>
|
|
: public sprout::unwrap_reference<T>
|
|
{};
|
|
|
|
//
|
|
// strip_reference
|
|
//
|
|
template<typename T>
|
|
struct strip_reference
|
|
: public sprout::identity<T>
|
|
{};
|
|
template<typename T>
|
|
struct strip_reference<sprout::reference_wrapper<T> >
|
|
: public sprout::identity<T&>
|
|
{};
|
|
template<typename T>
|
|
struct strip_reference<std::reference_wrapper<T> >
|
|
: public sprout::identity<T&>
|
|
{};
|
|
template<typename T>
|
|
struct strip_reference<T const>
|
|
: public sprout::strip_reference<T>
|
|
{};
|
|
template<typename T>
|
|
struct strip_reference<T volatile>
|
|
: public sprout::strip_reference<T>
|
|
{};
|
|
template<typename T>
|
|
struct strip_reference<T const volatile>
|
|
: public sprout::strip_reference<T>
|
|
{};
|
|
|
|
//
|
|
// unwrap_ref
|
|
//
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR typename sprout::unwrap_reference<T>::type&
|
|
unwrap_ref(T& t) {
|
|
return t;
|
|
}
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR typename sprout::unwrap_reference<T const>::type&
|
|
unwrap_ref(T const& t) {
|
|
return t;
|
|
}
|
|
|
|
//
|
|
// get_pointer
|
|
//
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR T*
|
|
get_pointer(sprout::reference_wrapper<T> const& r) {
|
|
return r.get_pointer();
|
|
}
|
|
template<typename T>
|
|
inline SPROUT_CONSTEXPR T*
|
|
get_pointer(std::reference_wrapper<T> const& r) {
|
|
return &r.get();
|
|
}
|
|
} // namespace sprout
|
|
|
|
#endif // #ifndef SPROUT_FUNCTIONAL_REF_HPP
|