Header file invoke.hpp

#define SIPLASPLAS_UTILITY_INVOKE_HPP 

#include "function_traits.hpp"

#include "logger.hpp"

#include <utility>

#include <functional>

#include <iostream>

namespace cpp
{
    namespace detail
    {
        template <typename Class, typename Object, bool IsBase = std::is_base_of<Class, Object>::value>
        class InvokeMemberFunction;
        
        template <typename Class, typename T>
        class InvokeMemberFunction<Class, std::reference_wrapper<T>, false>;
        
        template <typename Class, typename Object>
        class InvokeMemberFunction<Class, Object, false>;
        
        template <typename Class, typename Object, bool IsBase = std::is_base_of<Class, Object>::value>
        class InvokeMemberObject;
        
        template <typename Class, typename T>
        class InvokeMemberObject<Class, std::reference_wrapper<T>, false>;
        
        template <typename Class, typename Object>
        class InvokeMemberObject<Class, Object, false>;
        
        template <typename T, bool IsMemberObjectPointer = std::is_member_object_pointer<T>::value>
        class InvokeMember;
        
        template <typename T>
        class InvokeMember<T, false>;
    }
    
    template <typename Callable, typename ... Args>
    decltype(auto) invoke(Callable&& callable, Args&&... args);
    
    template <typename R, typename Class, typename ... Args>
    decltype(auto) invoke(R Class::* pointer, Args&&... args);
    
    template <typename R, typename Class, typename ... Params, typename ... Args>
    decltype(auto) invoke(R (Class::*)(Params...) const pointer, Args&&... args);
}