Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@SVTFOE_bunny

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

More than 1 year has passed since last update.

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

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;
}

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

0
Help us understand the problem. What is going on with this article?
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.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?