Template
62 lines
1.7 KiB
C++
62 lines
1.7 KiB
C++
#pragma once
|
|
#include <concepts>
|
|
|
|
namespace core {
|
|
|
|
template<typename T>
|
|
concept callable = requires { &T::operator(); };
|
|
|
|
template<typename T>
|
|
struct function_traits
|
|
{
|
|
using return_type = void;
|
|
using first_argument_type = void;
|
|
};
|
|
|
|
template<typename T>
|
|
requires callable<T>
|
|
struct function_traits<T>
|
|
{
|
|
using return_type = typename function_traits<decltype(&T::operator())>::return_type;
|
|
using first_argument_type = typename function_traits<decltype(&T::operator())>::first_argument_type;
|
|
};
|
|
|
|
template<typename Ret, typename Arg0, typename... Args>
|
|
struct function_traits<Ret(Arg0, Args...)>
|
|
{
|
|
using return_type = typename Ret;
|
|
using first_argument_type = typename Arg0;
|
|
};
|
|
|
|
template<typename Ret, typename Arg0, typename... Args>
|
|
struct function_traits<Ret (*)(Arg0, Args...)>
|
|
{
|
|
using return_type = typename Ret;
|
|
using first_argument_type = typename Arg0;
|
|
};
|
|
|
|
template<typename Ret, typename Class, typename Arg0, typename... Args>
|
|
struct function_traits<Ret (Class::*)(Arg0, Args...)>
|
|
{
|
|
using return_type = typename Ret;
|
|
using first_argument_type = typename Arg0;
|
|
};
|
|
|
|
template<typename Ret, typename Class, typename Arg0, typename... Args>
|
|
struct function_traits<Ret (Class::*)(Arg0, Args...) const>
|
|
{
|
|
using return_type = typename Ret;
|
|
using first_argument_type = typename Arg0;
|
|
};
|
|
|
|
template<typename T>
|
|
using return_type_t = typename function_traits<T>::return_type;
|
|
|
|
template<typename T>
|
|
using first_argument_type_t = typename function_traits<T>::first_argument_type;
|
|
|
|
template<typename T, typename Arg>
|
|
concept callable_with_converted_argument = requires(T&& callable, Arg&& arg) { callable(typename traits::first_argument_type_t<T>{arg}); };
|
|
|
|
}
|