Bug 1212745 - Part 1 - Make mozilla::Function support pointer to member function. r=nfroyd

This commit is contained in:
James Cheng 2015-10-11 19:53:00 +02:00
parent 74670a2e32
commit 6ed090b633
2 changed files with 80 additions and 3 deletions

View File

@ -44,23 +44,80 @@ class FunctionImplBase
{
public:
virtual ~FunctionImplBase() {}
virtual ReturnType call(Arguments... arguments) = 0;
virtual ReturnType call(Arguments... aArguments) = 0;
};
// Normal Callable Object.
template <typename Callable, typename ReturnType, typename... Arguments>
class FunctionImpl : public FunctionImplBase<ReturnType, Arguments...>
{
public:
explicit FunctionImpl(const Callable& aCallable)
: mCallable(aCallable) {}
ReturnType call(Arguments... aArguments) override
{
return mCallable(Forward<Arguments>(aArguments)...);
}
private:
Callable mCallable;
};
// Base class for passing pointer to member function.
template <typename Callable, typename ReturnType, typename... Arguments>
class MemberFunctionImplBase : public FunctionImplBase<ReturnType, Arguments...>
{
public:
explicit FunctionImpl(const Callable& aCallable) : mCallable(aCallable) {}
explicit MemberFunctionImplBase(const Callable& aCallable)
: mCallable(aCallable) {}
ReturnType call(Arguments... aArguments) override
{
return mCallable(Forward<Arguments>(aArguments)...);
return callInternal(Forward<Arguments>(aArguments)...);
}
private:
template<typename ThisType, typename... Args>
ReturnType callInternal(ThisType* aThis, Args&&... aArguments)
{
return (aThis->*mCallable)(Forward<Args>(aArguments)...);
}
template<typename ThisType, typename... Args>
ReturnType callInternal(ThisType&& aThis, Args&&... aArguments)
{
return (aThis.*mCallable)(Forward<Args>(aArguments)...);
}
Callable mCallable;
};
// For non-const member function specialization of FunctionImpl.
template <typename ThisType, typename... Args, typename ReturnType, typename... Arguments>
class FunctionImpl<ReturnType(ThisType::*)(Args...),
ReturnType, Arguments...>
: public MemberFunctionImplBase<ReturnType(ThisType::*)(Args...),
ReturnType, Arguments...>
{
public:
explicit FunctionImpl(ReturnType(ThisType::*aMemberFunc)(Args...))
: MemberFunctionImplBase<ReturnType(ThisType::*)(Args...),
ReturnType, Arguments...>(aMemberFunc)
{}
};
// For const member function specialization of FunctionImpl.
template <typename ThisType, typename... Args, typename ReturnType, typename... Arguments>
class FunctionImpl<ReturnType(ThisType::*)(Args...) const,
ReturnType, Arguments...>
: public MemberFunctionImplBase<ReturnType(ThisType::*)(Args...) const,
ReturnType, Arguments...>
{
public:
explicit FunctionImpl(ReturnType(ThisType::*aConstMemberFunc)(Args...) const)
: MemberFunctionImplBase<ReturnType(ThisType::*)(Args...) const,
ReturnType, Arguments...>(aConstMemberFunc)
{}
};
} // namespace detail
// The primary template is never defined. As |Signature| is required to be

View File

@ -23,7 +23,10 @@ struct ConvertibleToInt
int increment(int arg) { return arg + 1; }
struct S {
S() {}
static int increment(int arg) { return arg + 1; }
int decrement(int arg) { return arg - 1;}
int sum(int arg1, int arg2) const { return arg1 + arg2;}
};
struct Incrementor {
@ -82,6 +85,21 @@ TestReassignment()
CHECK(f(42) == 44);
}
static void
TestMemberFunction()
{
Function<int(S&, int)> f = &S::decrement;
S s;
CHECK((f(s, 1) == 0));
}
static void
TestConstMemberFunction()
{
Function<int(const S*, int, int)> f = &S::sum;
const S s;
CHECK((f(&s, 1, 1) == 2));
}
int
main()
{
@ -91,5 +109,7 @@ main()
TestLambda();
TestDefaultConstructionAndAssignmentLater();
TestReassignment();
TestMemberFunction();
TestConstMemberFunction();
return 0;
}