128 lines
4.2 KiB
C++
128 lines
4.2 KiB
C++
#ifndef FUNCTIONTRAITS_H
|
|
#define FUNCTIONTRAITS_H
|
|
|
|
#include <functional>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
|
|
template <typename T>
|
|
class FunctionTraits;
|
|
|
|
template <typename>
|
|
struct IsTuple : std::false_type {
|
|
enum {
|
|
num = 1,
|
|
};
|
|
};
|
|
|
|
template <typename... T>
|
|
struct IsTuple<std::tuple<T...>> : std::true_type {
|
|
enum {
|
|
num = std::tuple_size<std::tuple<T...>>::value,
|
|
};
|
|
};
|
|
|
|
template <typename... T>
|
|
struct IsTuple<std::pair<T...>> : std::true_type {
|
|
enum {
|
|
num = std::tuple_size<std::pair<T...>>::value,
|
|
};
|
|
};
|
|
|
|
template <typename Ret, typename... Args>
|
|
class FunctionTraits<Ret(Args...)> {
|
|
public:
|
|
enum { arity = sizeof...(Args), Results = IsTuple<Ret>::num };
|
|
using FunctionType = Ret(Args...);
|
|
using FunctionPointerType = FunctionType *;
|
|
using ReturnType = Ret;
|
|
using StlFunctionType = std::function<FunctionType>;
|
|
using Arguments = std::tuple<Args...>;
|
|
|
|
template <size_t I>
|
|
class Argument {
|
|
public:
|
|
static_assert(I < arity, "index is out of range, index must less than sizeof Args...");
|
|
using Type = std::tuple_element_t<I, Arguments>;
|
|
};
|
|
|
|
using FirstArgumentType = typename Argument<0>::Type;
|
|
};
|
|
|
|
template <typename Ret>
|
|
class FunctionTraits<Ret()> {
|
|
public:
|
|
enum { arity = 0, Results = IsTuple<Ret>::num };
|
|
using FunctionType = Ret();
|
|
using FunctionPointerType = FunctionType *;
|
|
using ReturnType = Ret;
|
|
using StlFunctionType = std::function<FunctionType>;
|
|
using Arguments = std::tuple<>;
|
|
using FirstArgumentType = void;
|
|
template <size_t I>
|
|
class Argument {
|
|
public:
|
|
using Type = void;
|
|
};
|
|
};
|
|
|
|
template <>
|
|
class FunctionTraits<std::nullptr_t> {
|
|
public:
|
|
using Arguments = std::tuple<>;
|
|
using FirstArgumentType = void;
|
|
template <size_t I>
|
|
class Argument {
|
|
public:
|
|
using Type = void;
|
|
};
|
|
};
|
|
|
|
template <typename Ret, typename... Args>
|
|
class FunctionTraits<Ret (*)(Args...)> : public FunctionTraits<Ret(Args...)> {};
|
|
|
|
template <typename Ret, typename... Args>
|
|
class FunctionTraits<std::function<Ret(Args...)>> : public FunctionTraits<Ret(Args...)> {};
|
|
|
|
template <typename Ret, typename ClassType, typename... Args>
|
|
class FunctionTraits<Ret (ClassType::*)(Args...)> : public FunctionTraits<Ret(Args...)> {};
|
|
|
|
template <typename Ret, typename ClassType, typename... Args>
|
|
class FunctionTraits<Ret (ClassType::*)(Args...) volatile> : public FunctionTraits<Ret(Args...)> {};
|
|
|
|
template <typename Ret, typename ClassType, typename... Args>
|
|
class FunctionTraits<Ret (ClassType::*)(Args...) const> : public FunctionTraits<Ret(Args...)> {};
|
|
|
|
template <typename Ret, typename ClassType, typename... Args>
|
|
class FunctionTraits<Ret (ClassType::*)(Args...) const volatile> : public FunctionTraits<Ret(Args...)> {};
|
|
|
|
// std::bind for object methods rclcpp/rclcpp/include/rclcpp/function_traits.hpp
|
|
template <typename ClassT, typename ReturnTypeT, typename... Args, typename... FArgs>
|
|
#if defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
|
|
struct FunctionTraits<std::_Bind<ReturnTypeT (ClassT::*(FArgs...))(Args...)>>
|
|
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
|
struct FunctionTraits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args...)>(FArgs...)>>
|
|
#elif defined _MSC_VER // MS Visual Studio
|
|
struct FunctionTraits<std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args...), FArgs...>>
|
|
#elif defined __clang__
|
|
struct FunctionTraits<std::__bind<ReturnTypeT (ClassT::*(FArgs...))(Args...)>>
|
|
#else
|
|
#error "Unsupported C++ compiler / standard library"
|
|
#endif
|
|
: FunctionTraits<ReturnTypeT(Args...)> {
|
|
};
|
|
|
|
// template <typename ClassT, typename ReturnTypeT, typename... Args, typename... FArgs>
|
|
// class FunctionTraits<std::_Bind<ReturnTypeT (ClassT::*(FArgs...))(Args...)>>
|
|
// : public FunctionTraits<decltype(std::_Bind<ReturnTypeT (ClassT::*(FArgs...))(Args...)>::operator())> {};
|
|
|
|
template <typename Callable>
|
|
class FunctionTraits : public FunctionTraits<decltype(&Callable::operator())> {};
|
|
|
|
template <typename Function>
|
|
typename FunctionTraits<std::decay_t<Function>>::StlFunctionType makeStlFunction(Function &&lambda) {
|
|
return static_cast<typename FunctionTraits<std::decay_t<Function>>::StlFunctionType>(
|
|
std::forward<Function>(lambda));
|
|
}
|
|
|
|
#endif // FUNCTIONTRAITS_H
|