gpt4 book ai didi

c++ - 我可以在基类模板方法中自动推导出子类型吗?

转载 作者:行者123 更新时间:2023-11-28 05:56:48 25 4
gpt4 key购买 nike

首先,让我提供一些背景信息。我正在为我的游戏创建一个小型游戏框架,其中有游戏系统和事件系统。我尝试使用模板等语言特性来避免用户代码中的样板代码。

有 Component 类,从中派生出其他游戏元素,即 Camera、Sprite、Button。

using EventType = unsigned int;
using EventCallback = std::function<void(Event)>;

class Component {
public:
// This is public version for general functor objects,
// particularly used with lambda
void addHandler(EventType type, const EventCallback &callback);

protected:
// Method for child classes. Creates event handler from method of the class.
//
// This is template method, because std::bind is used for functor creation,
// which requires class type at compile time.
template <class T>
void addHandler(EventType type, void (T::*method)(Event event)) { /*...*/ }
private:
// ...
};

每个组件都会监​​听一组特定的事件,因此它不必为每种可能的事件类型都实现处理程序。此外,组件用户应该能够添加自定义事件监听器,而无需为每个游戏元素创建新类,例如:

class Button : public Component {
public:
Button() {
addHandler(kOnTouch, &Button::onTouch);
}
// ...
};

Button ok, cancel;
ok.addHandler(kOnClick, [](Event) {
// ...
});

cancel.addHandler(kOnClick, [](Event) {
// ...
});

// Add another handler somewhere else in the code
cancel.addHandler(kOnClick, someCallback);

所以,我想做的是后期绑定(bind),对成员函数进行编译时检查。我想确保传递给 addHandler() 的方法指针属于调用 addHandler() 的子类。在 template argument deduction 的帮助下,我可以在 addHandler() 中获取方法所有者的类型.但是我没有找到推断子类类型的方法。在这里,我是如何尝试使用 decltype(*this) 和 type traits 来实现这一点的:

template <class T>
void addHandler(EventType type, void (T::*method)(Event event)) {
/***** This check is INCORRECT *****/
// Check that T is same as child class
using ChildClass = std::remove_reference<decltype(*this)>::type;
static_assert(std::is_same<T, ChildClass>::value,
"Event handler method must belong to caller class");

using namespace std::placeholders;

EventHandler::Callback callback =
std::bind(method, static_cast<T *>(this), _1);
addHandler(EventHandler(type, callback));
}

这里我们需要子类类型来与 T 进行比较。似乎 ChildClass 被分配给基组件类而不是 child 。有没有一种方法可以自动推断子类类型,仅在方法版本 addHandler() 内部进行更改?仅对这个重载的 addHandler() 而不是整个 Component 类进行模板化以最小化生成的代码并能够使用多态性是很重要的。所以它是更通用的 addHandler() 的微小包装,采用 std::function。

目前,我只能检查 T 是组件:

static_assert(std::is_base_of<Component, T>::value,
"Event handler method must belong to caller class");

最佳答案

It seems that ChildClass being assigned to base Component class rather than to child.

这里没有“分配”任何东西。滥用术语会造成混淆。

基类成员函数中this的类型(当然)是基类。

要了解调用者的类型,您需要调用者的this 指针,而不是基类成员函数中的this 指针.您可以通过要求调用者将其作为参数传递来获取调用者的 this 指针:

template <class T, class U>
void addHandler(EventType type, void (T::*method)(Event event), U* that)

然后你甚至不需要静态断言,你可以将 that 绑定(bind)到 method

注意如果您保留静态断言,您可能希望使用 std::is_base_of 而不是 std::is_same

或者,您可以摆脱 addHandler 重载,只需要派生类型进行绑定(bind):

class Button : public Component {
public:
Button() {
addHandler(kOnTouch, [this](Event e) { onTouch(e); });
}
// ...
};

关于c++ - 我可以在基类模板方法中自动推导出子类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34002018/

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