gpt4 book ai didi

c++ - C++中的事件委托(delegate)

转载 作者:行者123 更新时间:2023-11-30 03:31:38 24 4
gpt4 key购买 nike

我有以下委托(delegate)类:

    template <typename RetVal, typename ...Args>
class KxCEventDelegate
{
union InstancePtr
{
InstancePtr(void) : as_void(nullptr) {}

void* as_void;
const void* as_const_void;
};

typedef RetVal(*InternalFunction)(InstancePtr, Args&& ...args);
typedef std::pair<InstancePtr, InternalFunction> Stub;

// Turns a free function into internal function stub
template <RetVal(*Function)(Args ...args)>
static KX_INLINE RetVal FunctionStub(InstancePtr, Args&& ...args)
{
// we don't need the instance pointer because we're dealing with free functions
return (Function)(std::forward<Args>(args)...);
}

// Turns a member function into internal function stub
template <class C, RetVal (C::*Function)(Args ...args)>
static KX_INLINE RetVal ClassMethodStub(InstancePtr instance, Args&& ...args)
{
// cast the instance pointer back into the original class instance
return (static_cast<C*>(instance.as_void)->*Function)(std::forward<Args>(args)...);
}

// Turns a member function into internal function stub
template <class C, RetVal(C::*Function)(Args ...args) const>
static KX_INLINE RetVal ClassMethodStubConst(InstancePtr instance, Args&& ...args)
{
// cast the instance pointer back into the original class instance
return (static_cast<const C*>(instance.as_const_void)->*Function)(std::forward<Args>(args)...);
}

public:
// Binds a free function
template <RetVal(*Function)(Args ...args)>
void Bind(void)
{
m_stub.first.as_void = nullptr;
m_stub.second = &FunctionStub<Function>;
}

// Binds a class method
template <class C, RetVal (C::*Function)(Args ...args)>
void Bind(C* instance)
{
m_stub.first.as_void = instance;
m_stub.second = &ClassMethodStub<C, Function>;
}

// Binds a class method
template <class C, RetVal(C::*Function)(Args ...args) const>
void BindConst(const C* instance)
{
m_stub.first.as_const_void = instance;
m_stub.second = &ClassMethodStubConst<C, Function>;
}

// Invokes the delegate
RetVal Invoke(Args ...args) const
{
KX_ASSERT(m_stub.second != nullptr, "Cannot invoke unbound delegate. Call Bind() first.", m_stub.second, nullptr);
return m_stub.second(m_stub.first, std::forward<Args>(args)...);
}

private:
Stub m_stub;
};

用法是这样的(免费功能):

    int FreeFunctionInt(int i)
{
return i;
}

KxCEventDelegate<int, int> delegate;
delegate.Bind<&FreeFunctionInt>();
int ret = delegate.Invoke(10);

现在,我正在尝试实现一个类似于 C# 的通用 GetEventDelegate 函数。这是我带来的:

    // Gets event delegate.
template <typename RetVal, typename ...Args>
KxCEventDelegate<RetVal, Args...> GetEventDelegate(RetVal(*Function)(Args ...args))
{
KxCEventDelegate<RetVal, Args...> delegate;
delegate.Bind<Function>();
return delegate;
}

这是我无法弄清楚哪里出了问题的部分。好像是delegate.Bind<Function>();的问题.编译器给我以下错误:

1>------ Build started: Project: Tests, Configuration: Debug x64 ------
1>Main.cpp
1>c:\sdk\kx\kxengine\include\events\delegate.h(88): error C2672: 'kx::events::KxCEventDelegate<int,int>::Bind': no matching overloaded function found
1>c:\sdk\kx\tests\eventstests.h(76): note: see reference to function template instantiation 'kx::events::KxCEventDelegate<int,int> kx::events::GetEventDelegate<int,int>(RetVal (__cdecl *)(int))' being compiled
1> with
1> [
1> RetVal=int
1> ]
1>c:\sdk\kx\kxengine\include\events\delegate.h(88): error C2974: 'kx::events::KxCEventDelegate<int,int>::Bind': invalid template argument for 'C', type expected
1>c:\sdk\kx\kxengine\include\events\delegate.h(58): note: see declaration of 'kx::events::KxCEventDelegate<int,int>::Bind'
1>c:\sdk\kx\kxengine\include\events\delegate.h(88): error C2975: 'Function': invalid template argument for 'kx::events::KxCEventDelegate<int,int>::Bind', expected compile-time constant expression
1>c:\sdk\kx\kxengine\include\events\delegate.h(49): note: see declaration of 'Function'
1>Done building project "Tests.vcxproj" -- FAILED.

最佳答案

在此代码段中,您的通用 GetEventDelegate 函数:

template <typename RetVal, typename ...Args>
KxCEventDelegate<RetVal, Args...> GetEventDelegate(RetVal(*Function)(Args ...args)) {
KxCEventDelegate<RetVal, Args...> delegate;
delegate.Bind<Function>();
return delegate;
}

Function 不是常量表达式,如果您打算将它用作模板参数,它应该是常量表达式。
在 C++11/14 中,您可以使用另一个间接级别来解决它。像这样:

template <typename RetVal, typename ...Args>
struct Factory {
template<RetVal(*Function)(Args...)>
static KxCEventDelegate<RetVal, Args...> GetEventDelegate() {
KxCEventDelegate<RetVal, Args...> delegate;
delegate.Bind<Function>();
return delegate;
}
};

您可以按如下方式使用:

auto delegate = Factory<int, int>::GetEventDelegate<&FreeFunctionInt>();

无论如何,我建议改为向委托(delegate)类添加一个静态函数,并将其用作直接嵌入类型本身的工厂方法。
你最终会调用的东西:

auto delegate = KxCEventDelegate<int, int>::create<&FreeFunctionInt>();

至少从我的角度来看,读者更容易理解幕后发生的事情。

关于c++ - C++中的事件委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44084557/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com