首页 > 系统相关 >windows C++-使用 C++/WinRT 的集合

windows C++-使用 C++/WinRT 的集合

时间:2024-08-12 18:52:19浏览次数:13  
标签:std windows auto C++ vector values WinRT 集合 winrt

在内部,Windows 运行时集合具有大量复杂的移动部件。 但要将集合对象传递到 Windows 运行时函数,或要实现自己的集合属性和集合类型时,C++/WinRT 中有函数和基类可以提供支持。 这些功能消除复杂性,并节省大量时间和精力上的开销。

IVector 是由元素的任意随机访问集合实现的 Windows 运行时接口。 如果要自己实现 IVector,还需要实现 IIterable、IVectorView 和 IIterator。 即使需要自定义的集合类型,也需要做大量工作。 但如果你在 std::vector(或者 std::map 或 std::unordered_map)中有数据,而你想要做的只是将其传递到 Windows 运行时 API,那么如果可能你会希望避免进行该级别的工作。 要避免是有可能的,因为 C++/WinRT 可以帮助高效地创建集合,且无需花费太多精力。

空通用集合

本节介绍一个场景,在该场景中你希望创建初始为空的集合;然后在创建完毕后将其填充。

若要检索实现通用集合的类型的新对象,可以调用 winrt::single_threaded_vector 函数模板。 该对象作为 IVector 返回,并且它是一个接口,通过它可以调用所返回对象的函数和属性。

若要将以下代码示例直接复制并粘贴到 Windows 控制台应用程序 (C++/WinRT) 项目的主源代码文件中,请先在项目属性中设置“不使用预编译的标头” 。

// main.cpp
#include <winrt/Windows.Foundation.Collections.h>
#include <iostream>
using namespace winrt;

int main()
{
    winrt::init_apartment();

    Windows::Foundation::Collections::IVector<int> coll{ winrt::single_threaded_vector<int>() };
    coll.Append(1);
    coll.Append(2);
    coll.Append(3);

    for (auto const& el : coll)
    {
        std::cout << el << std::endl;
    }

    Windows::Foundation::Collections::IVectorView<int> view{ coll.GetView() };
}

如上述代码示例中所示,创建集合之后,你可以追加元素、对它们进行迭代,并且通常可以像处理从 API 接收到的任何 Windows 运行时集合对象那样处理对象。 如果需要集合的不可变视图,则可以调用 IVector::GetView,如下所示。 如上所示的模式(创建和使用集合)适用于想要将数据传入 API 或从 API 获取数据的简单方案。 可以将 IVector 或 IVectorView 传递到预期 IIterable 的任意位置。

在上述代码示例中,调用 winrt::init_apartment 会初始化 Windows 运行时中(默认在多线程单元中)的线程。 该调用还会初始化 COM。

从数据准备创建

本节介绍想要创建并填充集合的场景。你可以避免上述代码示例中调用“追加”的开销。 你可能已拥有源数据,或者可能更倾向于在创建 Windows 运行时集合对象之前填充源数据。 下面是操作方法。

auto coll1{ winrt::single_threaded_vector<int>({ 1,2,3 }) };

std::vector<int> values{ 1,2,3 };
auto coll2{ winrt::single_threaded_vector<int>(std::move(values)) };

for (auto const& el : coll2)
{
    std::cout << el << std::endl;
}

可将包含数据的临时对象传递给 winrt::single_threaded_vector,就像上方传递 coll1 那样。 也可以将 std:: vector(假设不会再次访问)移动到该函数中。 在这两种情况下,都会将右值传递到函数。 这确保编译器能够高效运作并避免复制数据。

如果想要将 XAML 项目控件绑定到集合,则可以执行以下操作。 但要明白,若要正确设置 ItemsControl.ItemsSource 属性,需要将其设置为 IInspectable 的 IVector 类型的值,或 IBindableObservableVector 等互操作性类型的值。

以下是代码示例,它生成适合绑定的类型集合,并向其追加元素。 可在 XAML 项目控件;绑定到 C++/WinRT 集合中查找到此代码的上下文。

auto bookSkus{ winrt::single_threaded_vector<Windows::Foundation::IInspectable>() };
bookSkus.Append(winrt::make<Bookstore::implementation::BookSku>(L"Moby Dick"));

可以从数据创建 Windows 运行时集合,并在集合上准备好视图以便传递给 API,完全无需复制任何内容。

std::vector<float> values{ 0.1f, 0.2f, 0.3f };
Windows::Foundation::Collections::IVectorView<float> view{ winrt::single_threaded_vector(std::move(values)).GetView() };

在上述示例中,我们创建的集合可以绑定到 XAML 项目控件;但是该集合是不可观测的。 

 可观测集合

若要检索实现可观测集合的类型的新对象,调用具有任何元素类型的 winrt::single_threaded_observable_vector 函数模板。 但要使可观测集合适合绑定到 XAML 项目控件,使用 IInspectable 作为元素类型。

该对象作为 IObservableVector 返回,并且它是一个接口,你(或它绑定到的控件)可以通过它调用所返回对象的函数和属性。

auto bookSkus{ winrt::single_threaded_observable_vector<Windows::Foundation::IInspectable>() };
 关联集合(映射)

以下是我们介绍的这两个函数的关联集合版本。

winrt::single_threaded_map 函数模板以 IMap 形式返回不可观测的关联集合。
winrt::single_threaded_observable_map 函数模板以 IObservableMap 形式返回可观测的关联集合。

通过向函数传递 std::map 或 std::unordered_map 类型的右值,可以选择为这些集合准备好数据。

auto coll1{
    winrt::single_threaded_map<winrt::hstring, int>(std::map<winrt::hstring, int>{
        { L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
    })
};

std::map<winrt::hstring, int> values{
    { L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
};
auto coll2{ winrt::single_threaded_map<winrt::hstring, int>(std::move(values)) };
 单线程

这些函数名称中的“单线程”表示它们不支持任何并发性,换言之,它们不是线程安全的。 此处提到的线程与单元无关,因为这些函数所返回的对象都是敏捷的。 但是指对象是单线程的。 如果只想跨应用程序二进制接口 (ABI) 以某种方式传递数据,那么这完全合适。

集合的基类

如果想要实现自定义集合以实现完全灵活,最好避免采用这种复杂的方式。 例如,如果没有 C++/WinRT 基类,以下就是自定义矢量视图的外观。

...
using namespace winrt;
using namespace Windows::Foundation::Collections;
...
struct MyVectorView :
    implements<MyVectorView, IVectorView<float>, IIterable<float>>
{
    // IVectorView
    float GetAt(uint32_t const) { ... };
    uint32_t GetMany(uint32_t, winrt::array_view<float>) const { ... };
    bool IndexOf(float, uint32_t&) { ... };
    uint32_t Size() { ... };

    // IIterable
    IIterator<float> First() const { ... };
};
...
IVectorView<float> view{ winrt::make<MyVectorView>() };

// 从 winrt::vector_view_base 结构模板派生自定义矢量视图,
// 并实现 get_container 函数来公开保存数据的容器,这样做要简单得多。

struct MyVectorView2 :
    implements<MyVectorView2, IVectorView<float>, IIterable<float>>,
    winrt::vector_view_base<MyVectorView2, float>
{
    auto& get_container() const noexcept
    {
        return m_values;
    }

private:
    std::vector<float> m_values{ 0.1f, 0.2f, 0.3f };
};

// get_container 返回的容器必须提供 winrt::vector_view_base 需要的 begin 和 end 接口。 
// 如上述示例所示,std::vector 支持这一点。 但你可以返回任何满足相同协定的容器,包括自定义容器。
struct MyVectorView3 :
    implements<MyVectorView3, IVectorView<float>, IIterable<float>>,
    winrt::vector_view_base<MyVectorView3, float>
{
    auto get_container() const noexcept
    {
        struct container
        {
            float const* const first;
            float const* const last;

            auto begin() const noexcept
            {
                return first;
            }

            auto end() const noexcept
            {
                return last;
            }
        };

        return container{ m_values.data(), m_values.data() + m_values.size() };
    }

private:
    std::array<float, 3> m_values{ 0.2f, 0.3f, 0.4f };
};

剩下的几种结构的定义:

// 1. winrt::vector_base
struct MyVector :
    implements<MyVector, IVector<float>, IVectorView<float>, IIterable<float>>,
    winrt::vector_base<MyVector, float>
{
    auto& get_container() const noexcept
    {
        return m_values;
    }

    auto& get_container() noexcept
    {
        return m_values;
    }

private:
    std::vector<float> m_values{ 0.1f, 0.2f, 0.3f };
};

// 2. winrt::observable_vector_base
struct MyObservableVector :
    implements<MyObservableVector, IObservableVector<float>, IVector<float>, IVectorView<float>, IIterable<float>>,
    winrt::observable_vector_base<MyObservableVector, float>
{
    auto& get_container() const noexcept
    {
        return m_values;
    }

    auto& get_container() noexcept
    {
        return m_values;
    }

private:
    std::vector<float> m_values{ 0.1f, 0.2f, 0.3f };
};

// 3. winrt::map_view_base
struct MyMapView :
    implements<MyMapView, IMapView<winrt::hstring, int>, IIterable<IKeyValuePair<winrt::hstring, int>>>,
    winrt::map_view_base<MyMapView, winrt::hstring, int>
{
    auto& get_container() const noexcept
    {
        return m_values;
    }

private:
    std::map<winrt::hstring, int> m_values{
        { L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
    };
};

// 4. winrt::map_base
struct MyMap :
    implements<MyMap, IMap<winrt::hstring, int>, IMapView<winrt::hstring, int>, IIterable<IKeyValuePair<winrt::hstring, int>>>,
    winrt::map_base<MyMap, winrt::hstring, int>
{
    auto& get_container() const noexcept
    {
        return m_values;
    }

    auto& get_container() noexcept
    {
        return m_values;
    }

private:
    std::map<winrt::hstring, int> m_values{
        { L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
    };
};

// 5. winrt::observable_map_base
struct MyObservableMap :
    implements<MyObservableMap, IObservableMap<winrt::hstring, int>, IMap<winrt::hstring, int>, IMapView<winrt::hstring, int>, IIterable<IKeyValuePair<winrt::hstring, int>>>,
    winrt::observable_map_base<MyObservableMap, winrt::hstring, int>
{
    auto& get_container() const noexcept
    {
        return m_values;
    }

    auto& get_container() noexcept
    {
        return m_values;
    }

private:
    std::map<winrt::hstring, int> m_values{
        { L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
    };
};

标签:std,windows,auto,C++,vector,values,WinRT,集合,winrt
From: https://blog.csdn.net/m0_72813396/article/details/140910776

相关文章

  • 2024华为OD笔试机试 - 模拟目录管理功能 (python/c++/java D卷C卷真题算法)
    华为OD机试(C卷+D卷)2024真题目录(Java&c++&python)题目描述实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。支持命令:创建目录命令:mkdir目录名称,如mkdirabc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作。此命令无输出......
  • C++类和对象(中):构造函数、析构函数、拷贝构造、赋值运算符重载
    文章目录C++类和对象4、类的默认成员函数5、构造函数5.1构造函数的特点5.2实例分析6、析构函数6.1析构函数的特点6.2实例分析7、拷贝构造函数7.1拷贝构造函数的特点7.2实例分析7.3浅拷贝和深拷贝8、赋值运算符重载8.1运算符重载8.1.1运算符重载的特点8.1.2实例分析8.......
  • windows下nginx配置开机自启动
    (1)、WindowsServiceWrapper工具下载工具下载URL:https://github.com/winsw/winsw/releases   (2)、WindowsServiceWrapper工具安装配置第一步:下载后将该工具放入Nginx的安装目录下,并且将其重命名为nginx-service.exe第二步:在nginx安装目录下新建服务日志文件夹:server......
  • BOOST c++库学习 之 boost.thread入门实战指南 使用boost.thread库以及读写锁mutex的
    Boost.Thread库简介1.概述Boost.Thread库是Boost库中专门用于处理多线程编程的模块。它提供了一组跨平台的线程管理和同步工具,帮助开发者在C++中更轻松地编写多线程程序。Boost.Thread的设计目标是使多线程编程更加简单、可靠,同时保持高效和可移植性。2.Boost.Thread......
  • Windows 更改 C盘用户目录下用户名
    Windows真是一个神奇的OS,在你安装系统的时候,你只要联网就要你用微软登录,其次你的用户名还是你的邮箱地址前5位字母,看起来非常难受,甚至有些人一直用的中文用户名,看来没吃过路径的亏。修改注册表win+R输入regedit,找到ProfileList。在S-1-5-开头的项,找到包含ProfileImage......
  • C/C++ 知识点:using 关键字
    文章目录一、using关键字1、命名空间别名和成员访问2、类型别名3、继承中的`using`声明4、模板别名5、模板中的`using`声明6、总结前言:C++中的using关键字是一个功能丰富的工具,它主要用于命名空间、类型别名、继承以及模板编程中。下面将详细介绍using关键字的几......
  • Linux C++ 开发3 - 你写的Hello world经过哪些过程才被计算机理解和执行?
    1.C/C++的编译过程1.1.预处理1.2.编译1.3.汇编1.3.1.汇编过程1.3.2.目标文件1.4.链接2.编译过程示例2.1.源代码2.2.逐步编译程序2.2.1.编译指令2.2.2.链接报错问题2.3.单步编译3.gcc/g++与gpp、as、ld的关系3.1.关系图3.2.示例演示......
  • Matlab卸载指南——for Windows
    Matlab卸载指南——forWindows背景:由于需要学习师兄的Simulink仿真的系统框图,需要使用R2022b及以上的版本才能打开文件。而本人的Matlab版本正好为R2022a……因此,不得不删掉旧版本的Matlab,去下载更新版本的软件。正好曾经上大学前捣鼓电脑时给自己下过一个Matlab,但由于乱操作......
  • dev c++的使用
    前置软件:devc++首先开始学习前,先把软件下好点开devc++,发现有一个页面如下图:这时按Ctrl+n即可打开一个页面如下:这时你是否已经跃跃欲试了吗,哦不,还得慢慢来先敲上一段代码#include<iostream>usingnamespacestd;intmain(){return0;}好了可以了就完了可以......
  • 开始梦幻之旅--C++
    生活中有许多人人在忙忙碌碌,其中的许多人s都不会想到他们会被代替那个代替别人的东西就是人工智能人工智能是什么,他由什么来做成的呢人工智能是什么早在二战时期,图灵就已经开始了图灵测试,具体如下:一名测试者写下自己的问题,随后将问题以纯文本的形式(如计算机屏幕和键盘)发送......