Мне нужно было что-то вроде std :: function, но затем я нашел this, который быстрее (как утверждает автор) и может даже сравниваться с оператором ==. Я приспособил его, чтобы динамический тип возвращаемого значения и аргументы, как это:Пользовательская реализация std :: function-like как для бесплатных, так и для функций-членов
template<typename TReturn, typename... TArgs>
class Delegate {};
template<typename TReturn, typename... TArgs>
class Delegate<TReturn(TArgs...)> final
{
private:
typedef void* InstancePointer;
typedef TReturn (*InternalFunction)(InstancePointer, TArgs...);
private:
// Turns a free function into our internal function stub
template <TReturn (*FreeFunction)(TArgs...)>
static TReturn FreeFunctionStub(InstancePointer instance, TArgs... args) {
// We don't need the instance pointer because we're dealing with free functions
return (FreeFunction)(std::forward<TArgs>(args)...);
}
// Turns a member function into our internal function stub
template <class TClass, TReturn (TClass::*MemberFunction)(TArgs...)>
static TReturn MemberFunctionStub(InstancePointer instance, TArgs... args) {
// Cast the instance pointer back into the original class instance
return (static_cast<TClass*>(instance)->*MemberFunction)(std::forward<TArgs>(args)...);
}
public:
Delegate() = default;
// Resets this delegate to a new free function
template <TReturn(*FreeFunction)(TArgs...)>
void reset() {
m_instance = nullptr;
m_function = &FreeFunctionStub<FreeFunction>;
}
// Resets this delegate to a new member function
template <class TClass, TReturn(TClass::*MemberFunction)(TArgs...)>
void reset(TClass* instance) {
m_instance = instance;
m_function = &MemberFunctionStub<TClass, MemberFunction>;
}
// Resets this delegate to a new free function
void specialReset(TReturn(*FreeFunction)(TArgs...)) {
m_instance = nullptr;
m_function = ???
}
// Resets this delegate to a new member function
template<class TClass>
void specialReset(TClass *instance, TReturn(TClass::*MemberFunction)(TArgs...)) {
m_instance = instance;
m_function = ???
}
// Invokes this delegate
TReturn invoke(TArgs... args) const {
if (m_function == nullptr)
throw new std::runtime_error(""Unbound delegate! Call reset() first."");
return m_function(m_instance, std::forward<TArgs>(args)...);
}
private:
InstancePointer m_instance;
InternalFunction m_function;
};
Использование идет так:
Delegate<void()> del1;
Delegate<int(double)> del2;
del1.reset<&someParameterlessVoidFreeFunction>();
del1.invoke();
del2.reset<SomeClass, &SomeClass::someIntMemberFunction>(&someClassInstance);
del2.invoke(24.2);
То, что я пытаюсь сделать, это добиться чего-то вроде этого (ИМО, гораздо чище и интуитивное):
Delegate<void()> del1;
Delegate<int(double)> del2;
del1.reset(&someParameterlessVoidFreeFunction);
del1.invoke();
del2.reset(&SomeClass::someIntMemberFunction, &someClassInstance);
del2.invoke(24.2);
Однако, я не совсем понимаю m_function
концепцию. То, что я пытаюсь достичь, даже возможно? Как я мог это сделать?
Кроме того, что именно представляет собой часть класса Делегат и почему нам нужно определить class Delegate {};
?
Является ли это для академической причины или практического? Для практического, вы, вероятно, сохраните много головных болей, используя 'std :: function' в любом случае, даже если это, как утверждается, медленнее. Вам, похоже, не нужна функция 'operator =='. – AndyG
Оператор == используется где-то, что не имеет значения. Я знаю о std :: function (это было сказано в самом начале), и я не хочу/не могу его использовать. –
Хорошо, я упомянул, что ваш синтаксис 'del2.reset (& SomeClass :: someIntMemberFunction, & someClassInstance);' вряд ли будет работать без какого-либо действительно взломанного кода, который устанавливает статические данные. Это связано с тем, что разница между передачей указателя функции в качестве аргумента шаблона в качестве аргумента параметра заключается в том, что значение аргумента шаблона известно во время компиляции (указатель функции является целым типом), а аргумент параметра неизвестен до времени выполнения , – AndyG