4

メンバー関数をパラメーターとして受け取るテンプレート関数を作成しました。

ただし、メンバー関数パラメーターの一部として使用する前にクラスを宣言する必要があるため、別のパラメーターにする必要があります。

template<typename C, void (C::*Method)(void)>
function<void(C*)> methodWrap()
{
}

つまり、テンプレートを明示的にインスタンス化するとき (メンバー ポインターを引数として渡すのではなく、これらのラッパーをコンパイル時に生成する必要があります)、使用するときに 2 回入力する必要があります。

function<void(C*)> someFunc = wrapMethod<SomeClass, &SomeClass::someMethod>();

なぜ私はtisのようなものを書くことができないのですか:

template<void (C::*Method)(void)>
function<void(C*)> methodWrap()
{
}

SomeClass を 2 回入力することなく、C の型とそのメンバー関数ポインターをキャプチャできるようにしますか?

または、C を「自由変数」として宣言し、推論を実行する内部テンプレート引数を持つ外部テンプレートでそれをラップできないのはなぜですか

template<typename C>
template<void (C::*Method)(void)>
function<void(C*)> methodWrap()
{
}
4

2 に答える 2

2

メンバー関数ポインターをテンプレートパラメーターにする代わりに、通常の関数パラメーターを使用して生活できる場合は、次のことができます。

#include <functional>

template<typename R, typename C, typename... Args>
struct MemberFunctionPointer
{
    typedef R Return;
    typedef C Class;
};

template<typename R, typename C>
constexpr auto inferMemberFunctionPointer(R (C::*method)())
{
    return MemberFunctionPointer<R,C>{};
}

template<typename T> 
constexpr auto methodWrap(T m)
{
    typedef typename decltype(inferMemberFunctionPointer(m))::Class Class;
    typedef typename decltype(inferMemberFunctionPointer(m))::Return Return;

        return std::function<Return (Class*)>();
}

struct B {};

struct A
{
    B f();   
};

void foo()
{
    auto const m = methodWrap( &A::f );
}

std::functionconstexpr型ではないため、methodWrap を使用してconstexpr変数を初期化することはできません。constexpr独自の単純なメンバー関数ラッパーを作成することで、これを回避できます。static_assertより良いエラーメッセージを取得するためにも追加しました。

#include <functional>

template<typename R, typename C, typename... Args>
struct MemberFunctionPointer
{
    typedef R Return;
    typedef C Class;
};

template<typename R, typename C>
constexpr auto inferMemberFunctionPointer(R (C::*method)() const)
{
    return MemberFunctionPointer<R,C>{};
}

template<typename R, typename C>
struct MemberFunction
{
    constexpr explicit MemberFunction(R (C::*g)() const): f(g) {}

    constexpr R operator()(C const* obj) const
    {
        return (obj->*f)();
    }

    R (C::*f)() const;
};

template<typename T> 
constexpr auto methodWrap(T m)
{
    static_assert( std::is_member_function_pointer<T>::value, 
                   "Member function pointer expected!");

    typedef typename decltype(inferMemberFunctionPointer(m))::Class Class;
    typedef typename decltype(inferMemberFunctionPointer(m))::Return Return;

        return MemberFunction<Return, Class>{ MemberFunctionPointer<Return,Class>{} };
}

struct B {};

struct A
{
    constexpr B f() const;   
};

void foo()
{
    auto constexpr m = methodWrap( &A::f );
    auto constexpr a = A{};
    m( &a );

    auto b = A{};
    m( &b );
}
于 2015-12-17T08:53:08.750 に答える