如何解决可变类模板参数缩减与可变参数函数模板参数缩减
可变参数类模板参数推导与可变参数函数模板参数推导有何不同?我目前有一个事件对象,它创建一个对象,该对象是某个基类的子类,每个子类的构造函数都采用非重叠类型和参数数量。我必须完成的课程看起来像这样
template <class T,class... Args>
struct CreateDrawableObjTreeEvent : RenderEvent {
CreateDrawableObjTreeEvent(Args&&... args) {
drawable = new T(std::forward<Args>(args)...);
}
T* drawable;
};
我想要实例化它的方式看起来像这样
RenderEvent* test = new CreateDrawableObjTreeEvent<DrawableObject>("testvertices");
其中 DrawableObject 构造函数接受 1 个字符串。当我尝试运行它时,我遇到了这个错误
'CreateDrawableObjTreeEvent<DrawableObject>::CreateDrawableObjTreeEvent': no overloaded function takes 1 argument
但是,当我重新设计类结构以便实例化发生在函数而不是它编译的构造函数中时没有问题
template <class T>
struct CreateDrawableObjTreeEvent : RenderEvent {
CreateDrawableObjTreeEvent() {}
template <class... Args>
void instantiate(Args&&... args) {
drawable = new T(std::forward<Args>(args)...);
}
T* drawable;
};
...
CreateDrawableObjTreeEvent<DrawableObject>* test = new CreateDrawableObjTreeEvent<DrawableObject>();
test->instantiate("testvertices");
我真的很想能够使用第一种方法的语法,有什么办法可以干净地实现这种行为吗?
解决方法
你可以得到
RenderEvent* test = new CreateDrawableObjTreeEvent<DrawableObject>("testvertices");
通过将类模板的可变参数部分移动到构造函数的模板中来工作
template <class T>
struct CreateDrawableObjTreeEvent : RenderEvent {
template <class... Args>
CreateDrawableObjTreeEvent(Args&&... args) :
drawable(new T(std::forward<Args>(args)...)) {}
T* drawable;
};
我应该注意的是,如果您尝试复制 CreateDrawableObjTreeEvent
的左值,则构造函数将被调用,因为将生成的函数是更好的匹配。要阻止这种情况,您需要向模板添加约束,或者您可以添加像
CreateDrawableObjTreeEvent(CreateDrawableObjTreeEvent& other) :
CreateDrawableObjTreeEvent(static_cast<const CreateDrawableObjTreeEvent&>(other)) {}
这将是更好的匹配,因为它不是模板。
,如果你可以使用 C++17,那么 CTAD (Class Template Argument Deduction) 你也可以推导出第一个模板参数 (T
),通过某种类型的包装器传递它。
我的意思是...假设你写的东西
template <typename>
struct wrap_t
{ };
template <typename T,typename... Args>
struct CreateDrawableObjectEvent : public RenderEvent
{
// ........................VVVVVVVVV
CreateDrawableObjectEvent (wrap_t<T>,Args && ... args)
: drawable{ new T{std::forward<Args>(args)...} }
{ }
std::unique_ptr<T> drawable;
};
您可以创建 test
传递如下
std::unique_ptr<RenderEvent>
test { new CreateDrawableObjectEvent{wrap_t<DrawableObject>{},"testvertices"} };
// .....................................^^^^^^^^^^^^^^^^^^^^^^^^
简单地使用从 CreateDrawableObjectEvent
构造函数生成的隐式 CTAD。
下面是一个完整的编译示例
#include <memory>
struct RenderEvent
{ };
struct DrawableObject
{
template <typename ... Args>
DrawableObject (Args...)
{ }
};
template <typename>
struct wrap_t
{ };
template <typename T,typename... Args>
struct CreateDrawableObjectEvent : public RenderEvent
{
CreateDrawableObjectEvent (wrap_t<T>,Args && ... args)
: drawable{ new T{std::forward<Args>(args)...} }
{ }
std::unique_ptr<T> drawable;
};
int main ()
{
std::unique_ptr<RenderEvent>
test { new CreateDrawableObjectEvent{wrap_t<DrawableObject>{},"testvertices"} };
}
未请求的建议:当你直接分配内存(new
/new[]
)时,请(please!)避免直接管理,而使用智能指针作为std::unique_ptr
/std::shared_prt
/etc.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。