Windows runtime 如何构造空的DeviceInformation集合?

Windows runtime 如何构造空的DeviceInformation集合?,windows-runtime,c++-winrt,Windows Runtime,C++ Winrt,我正在实现一个接口,它返回一个。实现可能超时(或失败),在这种情况下,我希望返回一个空集合。这是为了允许接口的客户端始终迭代返回的集合,而不管它是否成功,例如 auto&&devices{co_wait MyType::getDeviceAsync()}; 用于(自动和设备:设备) { //用“设备”做疯狂的事情 } 但是,我不知道如何构造一个空的DeviceInformationCollection。以下代码“有效”,但在客户端使用上述代码时会导致未定义的行为: IAsyncOperatio

我正在实现一个接口,它返回一个。实现可能超时(或失败),在这种情况下,我希望返回一个空集合。这是为了允许接口的客户端始终迭代返回的集合,而不管它是否成功,例如

auto&&devices{co_wait MyType::getDeviceAsync()};
用于(自动和设备:设备)
{
//用“设备”做疯狂的事情
}
但是,我不知道如何构造一个空的
DeviceInformationCollection
。以下代码“有效”,但在客户端使用上述代码时会导致未定义的行为:

IAsyncOperation MyType::GetDeviceAsync()
{
//做上师冥想
// ...
co_返回{nullptr};
}
我当前的解决方法是返回一个
IVector
,并在成功时将内部
DeviceInformation集合的项复制到向量中。这既乏味又低效。我更愿意按原样返回
DeviceInformationCollection
,并在失败时构造一个空集合


有办法做到这一点吗?

正式地说,这是不受支持的,因为DeviceInformation Collection类不提供创建自身空实例的方法。除非你能在Windows.Devices.Enumeration API中找到一些函数来为你实现这一点,否则你就不走运了

非正式地,我们可以观察到DeviceInformationCollection类的默认接口是IVectorView。这意味着此接口表示ABI上的类。因此,您可以利用这些知识玩一些把戏,但一般来说,这是非常危险的,因为接受DeviceInformation Collection作为输入的API可能会假定其实现是独占的,因此依赖于您可能不知道的某些内部布局。最好每次都以多态和安全的方式返回IVectorView。大概是这样的:

使用名称空间winrt;
使用名称空间Windows::Foundation;
使用名称空间Windows::Foundation::Collections;
使用命名空间Windows::Devices::Enumeration;
IAsyncOperation异步()
{
DeviceInformation Collection devices=co_wait/…某些异步调用
如果(设备)
{
co_返回装置;
}
//返回空的IVectorView。。。
返回单线程可观察向量().GetView();
}
int main()
{
用于(自动和设备:异步().get())
{
printf(“%ls\n”,device.Name().c_str());
}
}

正式地说,这是不受支持的,因为DeviceInformation Collection类不提供创建自身空实例的方法。除非你能在Windows.Devices.Enumeration API中找到一些函数来为你实现这一点,否则你就不走运了

非正式地,我们可以观察到DeviceInformationCollection类的默认接口是IVectorView。这意味着此接口表示ABI上的类。因此,您可以利用这些知识玩一些把戏,但一般来说,这是非常危险的,因为接受DeviceInformation Collection作为输入的API可能会假定其实现是独占的,因此依赖于您可能不知道的某些内部布局。最好每次都以多态和安全的方式返回IVectorView。大概是这样的:

使用名称空间winrt;
使用名称空间Windows::Foundation;
使用名称空间Windows::Foundation::Collections;
使用命名空间Windows::Devices::Enumeration;
IAsyncOperation异步()
{
DeviceInformation Collection devices=co_wait/…某些异步调用
如果(设备)
{
co_返回装置;
}
//返回空的IVectorView。。。
返回单线程可观察向量().GetView();
}
int main()
{
用于(自动和设备:异步().get())
{
printf(“%ls\n”,device.Name().c_str());
}
}

不太确定我是否理解正确。此代码“for(auto&&device:devices){}”是否发生异常?如果在“for循环”之前添加此行“If(devices==nullptr){}”,是否会发生异常?似乎您是对的,DeviceInformation Collection不能手动构造,我们只能返回nullptr。@fay:没错,执行基于范围的for循环会由于取消引用空指针而引发访问冲突。客户端代码可以添加一个检查(
if(devices){…}
),但我不希望我的接口给客户端带来额外的错误模式。我尝试将空的“IVector”转换为“DeviceInformation Collection”,以构造空的“DeviceInformation Collection”:
IVector myVector{winrt::single_threaded_vector()};DeviceInformationCollection myColl=myVector.as();
@fay:interest。我将其简化为
co_return single_threaded_vector()。as();
,它似乎按预期工作。虽然底层的
std::vector
在退出方法的过程中确实会被破坏,而且我不确定其影响。实际上,我不确定
IVectorView
接口的所有权语义,换句话说:这是否因为代码是correct,或者这不会失败,因为指向
std::vector
的指针(悬空)从未被取消引用?我的测试基于代码。“as”函数返回请求的接口,“DeviceInformation Collection”从“IVectorView”继承,所以我尝试使用“as”函数将“IVector”转换为“DeviceInformation Collection”。但实际上我不太清楚基本原理。不太确定我是否理解正确。此代码“for(auto&&device:devices){}”是否发生异常?如果在“for循环”之前添加这行“if(devices==nullptr){}”,是否会发生异常?您似乎是对的,DeviceInformationCollection不能手动构造,我们只能返回nullptr。@fay:对,执行基于范围的loo