#include <functional>
enum ParameterType
{
POINTER_PARAMETER,
ARRAY_PARAMETER
};
template <typename WrappedType, ParameterType ParamType, bool IsOutputParameter>
class WrappedParameter;
template <bool b>
struct BoolWrapper {};
template <typename WrappedType, bool IsOutputParameter>
class WrappedParameter<WrappedType, POINTER_PARAMETER, IsOutputParameter>
{
public:
typedef WrappedParameter type;
WrappedParameter(WrappedType in_value) : m_value(in_value)
{
//static_assert(std::is_pointer<WrappedType>::value, "Must be a pointer type.");
}
WrappedType GetWrapped() const
{
return m_value;
}
private:
WrappedType m_value;
};
template <typename WrappedType, bool IsOutputParameter>
class WrappedParameter<WrappedType, ARRAY_PARAMETER, IsOutputParameter>
{
public:
typedef WrappedParameter type;
WrappedParameter(WrappedType in_value, size_t* in_count) : m_value(in_value), m_count(in_count)
{
//static_assert(std::is_pointer<WrappedType>::value, "Must be a pointer type.");
}
WrappedType GetWrapped() const
{
return m_value;
}
private:
WrappedType m_value;
size_t* m_count;
};
template <typename T>
struct ParameterUnwrapper
{
static T UnwrapParameter(const T& in_param)
{
return in_param;
}
};
template <typename T, ParameterType ParamType, bool IsOutputParameter>
struct ParameterUnwrapper<WrappedParameter<T, ParamType, IsOutputParameter>>
{
static T UnwrapParameter(const WrappedParameter<T, ParamType, IsOutputParameter>& in_param)
{
return in_param.GetWrapped();
}
};
template <typename T>
T UnwrapParameter(T in_param)
{
return ParameterUnwrapper<T>::UnwrapParameter(in_param);
}
template <typename T>
WrappedParameter<T, ARRAY_PARAMETER, true> WrapOutputArrayParameter(T in_param, size_t* in_count)
{
return WrappedParameter<T, ARRAY_PARAMETER, true>(in_param, in_count);
}
class A
{
public:
virtual int DoStuff(int a, int** b, size_t *c) { *b = new int[2 * a]; *c = 2 * a; return 0; };
};
A* m_wrapped = new A();
template <typename MemFunc, typename ...Args>
int ExecuteAndLog(
MemFunc in_memberFunction,
const std::string& in_methodName,
Args... args) //-> decltype((m_wrapped->*in_memberFunction)(UnwrapParameter(args)...))
{
return ExecuteFunctorAndLog(
[&]() { return (m_wrapped->*in_memberFunction)(UnwrapParameter(args)...); },
in_methodName,
args...);
}
template <typename Functor, typename ...Args>
auto ExecuteFunctorAndLog(
Functor in_functor,
const std::string& in_functorName,
Args... argsToLog) -> decltype(in_functor())
{
return in_functor();
}
int main()
{
int *result = NULL;
size_t resultSize;
return ExecuteAndLog(&A::DoStuff, "DoStuff", 5, WrapOutputArrayParameter(&result, &resultSize), &resultSize);
}