LoginSignup
0

More than 3 years have passed since last update.

C++でメンバー関数を、thisを第1引数にとる関数ポインタに変換する

Last updated at Posted at 2019-08-05
  • 2019/08/07 コメントを反映しておされになった

本文

vc2019で実験。

  • 非型テンプレートパラメータのauto宣言(関数ポインタをtemplate引数にする) c++17
  • local class c++11
  • valiadic template c++11
  • ラムダ式と単項+演算子 c++ ? unary + operator
#include <iostream>

namespace {

template <auto M, // R (C::*M)(ARGS...) なのだがautoでないとARGS...があって指定することができない
typename R, typename C, typename... ARGS>
constexpr auto _OpenMethod(R (C::*m)(ARGS...))
{
#if false
    struct inner // local class
    {
        static R call(C *self, ARGS... args)
        {
            return (self->*M)(args...);
        }
    };
    return &inner::call; // static関数なので普通の関数ポインタ
#else
    // コメントで教えてもらった方法でアップグレード
    return +[](C *self, ARGS... args){ return (self->*M)(args...); };
#endif
}

template <auto M>
constexpr auto OpenMethod()
{
    return _OpenMethod<M>(M);
}

}

struct Some
{
    int Value = 0;

    int Plus(int n)
    {
        Value += n;
        return Value;
    }
};

int main()
{
    constexpr auto f = OpenMethod<&Some::Plus>();
    std::cout << typeid(f).name() << std::endl;
    // int (__cdecl*)(struct Some * __ptr64,int)

    Some some;
    some.Plus(1);

    auto result = f(&some, 2);
    std::cout << result << std::endl;
    // 3

    return 0;
}

実用的に使うべく、
MsgPack-RPC の関数登録や、Lua の関数登録に応用できないか試行錯誤しているところでございます。

最近の C++ 知らない間に強まっている・・・

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0