【发布时间】:2021-08-26 23:07:39
【问题描述】:
我试图概括这个 COM 对象自动管理类,但我什至不确定它是否可能。目前,我已经为 1、2 和 3 指针定义了它,但我想让它成为适用于所有情况的单一实现。
手动实施:
#include <concepts>
#include <type_traits>
#include <Unknwn.h>
template <std::derived_from<IUnknown> COMInterface>
struct AutoManagedCOMObj {
COMInterface* ptr;
template<std::invocable<COMInterface**> Invocable>
AutoManagedCOMObj(Invocable initializer) {
HRESULT hr = initializer(&ptr);
if (FAILED(hr)) exit(hr);
}
~AutoManagedCOMObj() {
ptr->Release();
}
};
template <
std::derived_from<IUnknown> COMInterface1,
std::derived_from<IUnknown> COMInterface2
>
struct AutoManaged2COMObjs {
COMInterface1* ptr1;
COMInterface2* ptr2;
template<std::invocable<COMInterface1**, COMInterface2**> Invocable>
AutoManaged2COMObjs(Invocable initializer) {
HRESULT hr = initializer(&ptr1, &ptr2);
if (FAILED(hr)) exit(hr);
}
~AutoManaged2COMObjs() {
ptr2->Release();
ptr1->Release();
}
};
template <
std::derived_from<IUnknown> COMInterface1,
std::derived_from<IUnknown> COMInterface2,
std::derived_from<IUnknown> COMInterface3
>
struct AutoManaged3COMObjs {
COMInterface1* ptr1;
COMInterface2* ptr2;
COMInterface3* ptr3;
template<std::invocable<COMInterface1**, COMInterface2**, COMInterface3**> Invocable>
AutoManaged3COMObjs(Invocable initializer) {
HRESULT hr = initializer(&ptr1, &ptr2, &ptr3);
if (FAILED(hr)) exit(hr);
}
~AutoManaged3COMObjs() {
ptr3->Release();
ptr2->Release();
ptr1->Release();
}
};
一般解决方案的初始尝试:
template<
std::derived_from<IUnknown> ... T
>
struct AutoManagedCOMObjs {};
template<
std::derived_from<IUnknown> COMInterface,
std::derived_from<IUnknown>... Rest
>
struct AutoManagedCOMObjs<COMInterface, Rest ...> {
COMInterface* first;
AutoManagedCOMObjs<Rest ...> rest;
template<std::invocable<COMInterface**, Rest** ...> Invocable>
AutoManagedCOMObjs(Invocable initializer) {
HRESULT hr = initializer(&first, &rest...);
if (FAILED(hr)) exit(hr);
}
~AutoManagedCOMObjs() {
// the dtor is an unsolved problem as well
//ptr2->Release();
//ptr1->Release();
}
};
我无法找到将结构声明中的 ... Rest 与 invocable 参数签名联系起来的方法。
如果有帮助的话。 VS 在告诉我
错误“...”:没有可用的参数包 展开(指 ctor 的第一行)。
对于上下文,这就是我使用这些类之一的方式:
AutoManagedCOMObj<ID3D11Texture2D> back_buffer_interface([](ID3D11Texture2D** ptr){
return swap_chain->GetBuffer(0, uuid(ptr), (void**)ptr);
});
【问题讨论】:
-
你的问题很清楚,但如果你发minimal reproducible example 会很有帮助。如果无法访问您未显示的标题,我们必须自己重新创建您的情况。
-
(1) 有什么理由使用原始指针(例如
COMInterface1* ptr1;)而不是一些智能指针(RAII)? (2) 不初始化指向nullptr的指针? (3) 不检查它们不是空值就释放它们? (4) 在发生错误时调用exit,而不是抛出异常并进行适当的清理。 (5) 要使用 C 样式转换而不是reinterpret_cast<void **>(ptr)? (6) 在使用代码 (back_buffer_interface) 时不要将该函数作为模板以避免强制转换? (7) 在掌握基本良好实践之前尝试编写高级 C++ 可变参数模板?
标签: c++ variadic-templates c++-concepts