Files
klubhaus-doorbell/libraries/FastLED/src/fl/functional.h
2026-02-12 00:45:31 -08:00

98 lines
3.4 KiB
C++

#pragma once
#include "fl/type_traits.h"
#include "fl/utility.h"
namespace fl {
template <typename T>
class Ptr; // Forward declare Ptr to avoid header inclusion
template <typename T, typename Deleter>
class unique_ptr; // Forward declare unique_ptr to avoid header inclusion
//----------------------------------------------------------------------------
// invoke implementation - equivalent to std::invoke from C++17
//----------------------------------------------------------------------------
namespace detail {
// Helper to detect member data pointers
template <typename T>
struct is_member_data_pointer : false_type {};
template <typename T, typename C>
struct is_member_data_pointer<T C::*> : integral_constant<bool, !is_function<T>::value> {};
// Helper to detect if T is a pointer type
template <typename T>
struct is_pointer_like : false_type {};
template <typename T>
struct is_pointer_like<T*> : true_type {};
template <typename T>
struct is_pointer_like<fl::Ptr<T>> : true_type {};
template <typename T, typename Deleter>
struct is_pointer_like<fl::unique_ptr<T, Deleter>> : true_type {};
// Helper to detect if we should use pointer-to-member syntax
template <typename T>
struct use_pointer_syntax : is_pointer_like<typename remove_reference<T>::type> {};
} // namespace detail
// Main invoke function overloads
// 1a. Member function pointer with object reference
template <typename F, typename T1, typename... Args>
auto invoke(F&& f, T1&& t1, Args&&... args)
-> enable_if_t<is_member_function_pointer<typename remove_reference<F>::type>::value &&
!detail::use_pointer_syntax<T1>::value,
decltype((fl::forward<T1>(t1).*f)(fl::forward<Args>(args)...))>
{
return (fl::forward<T1>(t1).*f)(fl::forward<Args>(args)...);
}
// 1b. Member function pointer with pointer-like object
template <typename F, typename T1, typename... Args>
auto invoke(F&& f, T1&& t1, Args&&... args)
-> enable_if_t<is_member_function_pointer<typename remove_reference<F>::type>::value &&
detail::use_pointer_syntax<T1>::value,
decltype(((*fl::forward<T1>(t1)).*f)(fl::forward<Args>(args)...))>
{
return ((*fl::forward<T1>(t1)).*f)(fl::forward<Args>(args)...);
}
// 2a. Member data pointer with object reference
template <typename F, typename T1>
auto invoke(F&& f, T1&& t1)
-> enable_if_t<detail::is_member_data_pointer<typename remove_reference<F>::type>::value &&
!detail::use_pointer_syntax<T1>::value,
decltype(fl::forward<T1>(t1).*f)>
{
return fl::forward<T1>(t1).*f;
}
// 2b. Member data pointer with pointer-like object
template <typename F, typename T1>
auto invoke(F&& f, T1&& t1)
-> enable_if_t<detail::is_member_data_pointer<typename remove_reference<F>::type>::value &&
detail::use_pointer_syntax<T1>::value,
decltype((*fl::forward<T1>(t1)).*f)>
{
return (*fl::forward<T1>(t1)).*f;
}
// 3. Regular callable (function pointer, lambda, functor)
template <typename F, typename... Args>
auto invoke(F&& f, Args&&... args)
-> enable_if_t<!is_member_function_pointer<typename remove_reference<F>::type>::value &&
!detail::is_member_data_pointer<typename remove_reference<F>::type>::value,
decltype(fl::forward<F>(f)(fl::forward<Args>(args)...))>
{
return fl::forward<F>(f)(fl::forward<Args>(args)...);
}
} // namespace fl