Help us understand the problem. What is going on with this article?

関数オブジェクトから関数のシグネチャを取得する

関数オブジェクトから関数のシグネチャを取得するテンプレートクラスを作ってみました
戻り値、引数や修飾子情報を取れます

1.シグネチャ取得

FuncSignature.h
template<class _RetType, class... _Args>
struct FuncSignatureAbstract
{
    //!<@brief  戻り値の型
    using RetType = _RetType;
    //!<@brief  引数群の型(tuple型)
    using ArgsType = std::tuple<_Args...>;

    //  インデックス指定の型
    template <size_t index>
    struct Arg
    {
    using Type = typename std::tuple_element<index, 
               std::tuple<_Args...>>::type;
    };

    //!<@brief  引数の数を取得
    static  constexpr size_t ArgsLength() { return sizeof...(_Args); }

    //!<@brief  引数群のサイズを取得
    static  constexpr size_t ArgsSize() {
        constexpr ArgsType args;
        size_t size = 0ULL;
        TupleForEach(args, [&size](auto it) {
        size += sizeof(decltype(it));
        });
        return size;
        }

        //!<@brief  戻り値の型サイズを取得
        static  constexpr size_t RetTypeSize()
        {
            return SizeOf<RetType>::GetSize();
        }


    private:
        template<class T>
        struct SizeOfDefault {
            static constexpr size_t GetSize() { return sizeof(T); }
        };

        template<class T>
        struct SizeOf : SizeOfDefault<T> {};

        template<>
        struct SizeOf<void>
        {
            static constexpr size_t GetSize() { return 0; }
        };

     template<class... Types, typename FuncType>
     constexpr void TupleForEach(const std::tuple<Types...>& _tuple, FuncType func)
       {
            std::apply([&](auto... args) constexpr {
                (func(args), ...);
                }, _tuple);
       }
};


template<class _ClassType, class _RetType, class... _Args>
        struct FuncSignatureMemberFunc : public FuncSignatureAbstract<_RetType, _Args...>
        {
            //!<@brief  クラス型
            using ClassType = _ClassType;

            //!<@brief  メンバ関数か
            static  constexpr   bool    IsMemberFunc() { return false; }
        };



template<typename T>
struct FuncSignatureSignature;

template<class _RetType, class... _ArgsType>
struct FuncSignature<_RetType(*)(_ArgsType...)> : 
    public Detail::FuncSignatureAbstract<_RetType, _ArgsType...>
{
    //  修飾子情報
    //!<@brief  constか
    static  constexpr   bool    IsConst() { return false; }
    //!<@brief  volatileか
    static  constexpr   bool    IsVolatile() { return false; }
    //!<@brief  メンバ関数か
    static  constexpr   bool    IsMemberFunction() { return false; }
};

template<class ClassType, class _RetType, class... _ArgsType>
struct FuncSignature<_RetType(ClassType::*)(_ArgsType...)> :
    public Detail::FuncSignatureMemberFunc<ClassType, _RetType, _ArgsType...>
{
    //  修飾子情報
    //!<@brief  constか
    static  constexpr   bool    IsConst() { return false; }
    //!<@brief  volatileか
    static  constexpr   bool    IsVolatile() { return false; }
};

template<class ClassType, class _RetType, class... _ArgsType>
struct FuncSignature<_RetType(ClassType::*)(_ArgsType...)const> :
    public Detail::FuncSignatureMemberFunc<ClassType, _RetType, _ArgsType...>
{
    //  修飾子情報
    //!<@brief  constか
    static  constexpr   bool    IsConst() { return true; }
    //!<@brief  volatileか
    static  constexpr   bool    IsVolatile() { return false; }
};

template<class ClassType, class _RetType, class... _ArgsType>
struct FuncSignature<_RetType(ClassType::*)(_ArgsType...)volatile> :
    public Detail::FuncSignatureMemberFunc<ClassType, _RetType, _ArgsType...>
{
    //  修飾子情報
    //!<@brief  constか
    static  constexpr   bool    IsConst() { return false; }
    //!<@brief  volatileか
    static  constexpr   bool    IsVolatile() { return true; }
};

template<class ClassType, class _RetType, class... _ArgsType>
struct FuncSignature<_RetType(ClassType::*)(_ArgsType...)const volatile> :
    public Detail::FuncSignatureMemberFunc<ClassType, _RetType, _ArgsType...>
{
    //  修飾子情報
    //!<@brief  constか
    static  constexpr   bool    IsConst() { return true; }
    //!<@brief  volatileか
    static  constexpr   bool    IsVolatile() { return true; }
};

main.cpp
class Test
{
public:
 int Func(int, float)const{return 0}
}

int main()
{

// 引数の数
constexpr auto argsLength = FuncSignature<decltype(&Test::Func)>::ArgsLength();

return 0;
}

2.おまけ

これを使って任意の関数を実行できるクラスも適当に作ってみました

anyFunc
class AnyFunc
{
public:
    constexpr AnyFunc()noexcept :
        mObjectPtr(nullptr),
        mIsConst(false),
        mIsVolatile(false),
        mIsMemberFunc(false),
        mArgsLength(0U),
        mArgsSize(0ULL),
        mClassSize(0ULL){}

    template<class _ClassType, class _RetType, class... _ArgsType>
    AnyFunc(_RetType(_ClassType::*objPtr)(_ArgsType...)const):
        mObjectPtr(force_cast<void*>(objPtr)),
        mIsConst(true),
        mIsVolatile(false),
        mIsMemberFunc(true),
        mArgsLength(GetSignature<decltype(objPtr)>::ArgsLength()),
                mArgsSize(GetSignature<decltype(objPtr)>::ArgsSize()),
        mClassSize(sizeof(GetSignature<decltype(objPtr)>::ClassType ))
    {

    }

    template<class RetType = void, class ClassType, class... Args>
    RetType Invoke(ClassType* classPtr, Args... args) const
    {
        using ObjPtrType = RetType(ClassType::*)(Args...);
        ObjPtrType ptr = force_cast<ObjPtrType>(mObjectPtr);

                _wassert(mClassSize == sizeof(ClassType), L"");
        _wassert(mArgsLength == GetSignature<decltype(ptr )>::ArgsSize(), L"");
                _wassert(mArgsSize == sizeof...(Args), L"");

        if constexpr (std::is_same<void, RetType>::value == false)
        {
            return (classPtr->*ptr)(args...);
        }
        else
        {
            (classPtr->*ptr)(args...);
        }
    }

    inline  bool    IsConst()const { return mIsConst; }
    inline  bool    IsVolatile()const { return mIsVolatile; }
    inline  bool    IsMemberFunc()const { return mIsMemberFunc; }
    inline  u32 IsArgsLength()const { return mArgsLength; }

private:
    //!<@brief  オブジェクト
    void* mObjectPtr;
    //!<@brief  const型か
    bool    mIsConst;
    //!<@brief  volatile型か
    bool    mIsVolatile;
    //!<@brief  メンバ関数か
    bool    mIsMemberFunc;
    //!<@brief  引数の数
    u32     mArgsLength;
    //!<@brief  引数群のサイズ
    size_t  mArgsSize;
    //!<@brief  クラスのサイズ
    size_t  mClassSize;
};

main.cpp
class Test
{
public:
 int Func(int, float)const{return 0}
}

int main()
{

AnyFunc anyFunc(&Test::Func);
anyFunc.Invoke<int>(testObj, 1, 2.0f);

return 0;
}

色々とガバガバです
使いどころもわかりません

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした