如何创建一个可变结构,它采用与 ctor 参数相同的 "variadic invocable"?
How to create a variadic struct that takes a "variadic invocable" of the same arity as the ctor parameter?
我正在尝试推广此 COM 对象自动管理 class,但我什至不确定是否可行。目前,我已经为 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告诉我
Error '...': there are no parameter packs available to
expand (referring to the first line of the ctor).
对于上下文,这就是我使用这些 classes 之一的方式:
AutoManagedCOMObj<ID3D11Texture2D> back_buffer_interface([](ID3D11Texture2D** ptr){
return swap_chain->GetBuffer(0, uuid(ptr), (void**)ptr);
});
std::tuple
(with std::apply
) 可能有帮助:
template <std::derived_from<IUnknown>... Ts>
struct AutoManagedCOMObj
{
std::tuple<Ts*...> tuple_ptrs;
template<std::invocable<Ts**...> Invocable>
AutoManagedCOMObj(Invocable initializer)
{
HRESULT hr = std::apply([&](auto*&... ptrs){ return initializer(&ptrs...);},
tuple_ptrs);
if (FAILED(hr)) exit(hr);
}
~AutoManagedCOMObj()
{
std::apply([](auto*... ptrs){ (ptrs->Release(), ...); }, tuple_ptrs);
}
};
我正在尝试推广此 COM 对象自动管理 class,但我什至不确定是否可行。目前,我已经为 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告诉我
Error '...': there are no parameter packs available to expand (referring to the first line of the ctor).
对于上下文,这就是我使用这些 classes 之一的方式:
AutoManagedCOMObj<ID3D11Texture2D> back_buffer_interface([](ID3D11Texture2D** ptr){
return swap_chain->GetBuffer(0, uuid(ptr), (void**)ptr);
});
std::tuple
(with std::apply
) 可能有帮助:
template <std::derived_from<IUnknown>... Ts>
struct AutoManagedCOMObj
{
std::tuple<Ts*...> tuple_ptrs;
template<std::invocable<Ts**...> Invocable>
AutoManagedCOMObj(Invocable initializer)
{
HRESULT hr = std::apply([&](auto*&... ptrs){ return initializer(&ptrs...);},
tuple_ptrs);
if (FAILED(hr)) exit(hr);
}
~AutoManagedCOMObj()
{
std::apply([](auto*... ptrs){ (ptrs->Release(), ...); }, tuple_ptrs);
}
};