IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> d的元数据 -> 正文阅读

[C++知识库]d的元数据

原文
提议添加新的__metadata存储类,来标记函数聚集声明成员字段.

理由和动机

类型限定符传递性地应用于所有子类型:

struct A
{
    int a;
    int* b;
}

void main()
{
    不变 A a;//aa和ab都是不变
}

但是有时,无论如何限定,特定字段要保持可变.如下示例:
标准库数组RefCounted的用法:

struct RefCounted(T)
{
    T data;
    size_t count;

    /* RefCounted方法*/
}

struct Array(T)
{
    private struct Payload
    {
        T[] payload;
        size_t capacity;
    }
    private RefCounted!Payload _data;

    /* Array方法*/
}

void main()
{
    不变 Array!(int*) arr;
}

上例,声明不变数组.根据当前语言规则,引用计数字段的_data成员是不变,使得RefCountedcount成员,也是不变.导致无法按全封装方式计算不变对象引用.

std.datetimeRebindable用法:

struct Rebindable(T)
{
    import std.traits : Unqual;
    private union
    {
        T original;
        Unqual!T stripped;
    }

    //其他有趣的方法
}

class TimeZone {}

struct SysTime
{
    Rebindable!(不变 TimeZone) _timezoneStorage;
}

void main()
{
    不变 SysTime a;
}

不变声明SysTime实例时,SysTime可重绑定对象也使不变无用:可重绑定对象的全部意义在于绑定其他.
一般按对象一部分声明分配器.如果上述对象不变,则分配器无法修改其内部数据.
以上,限定符传递性使得很难编写干净,封装代码.为了缓解这些问题,需要打破限定符传递性的方法.因而引入__metadata:可在成员字段的声明中使用,从而打断传递性.如:

struct RefCounted(T)
{
    T data;
    size_t count;

    /* RefCounted方法*/
}

struct Array(T)
{
    private struct Payload
    {
        T[] payload;
        size_t capacity;
    }
    private __metadata RefCounted!Payload _data;

    /* 数组方法 */
}

void main()
{
    不变 Array!(int*) arr;
}

现在按__metadata标记RefCounted对象,即使对象自身是不变,ArrayRefCounted内部都可修改他们,这样达到引用计数目的.

语义

__metadata存储类修改字段上类型限定符的传播性.__metadata只可应用于private,可变成员.

struct S
{
    int* p;
    shared int* s;
    private __metadata
    {
        int* m;
        shared int* ms;
    }
    __metadata int* pm;
//错误:`__metadata`字段必须是`private`
    private __metadata const int* mc;
//错误:不能同时是__metadata和const
    private __metadata immutable int* imc;
//错误:不能既是__metadata又是不变的
}

除了__metadata字段,不变仍是可传递的.修改__metadata字段,是已定义的行为.

struct S
{
    int p;
    private __metadata int m;

    void increment() immutable
    {
        ++m;// 好,m是元数据
        ++p;//错误,无法修改S不变实例的p字段
    }
}

__metadata不应用传递性.

struct RefCount
{
    immutable size_t id;
    size_t count;
}

struct T
{
    private __metadata RefCount s;

    void updateRC() immutable
    {
        ++s.count;    // 好
        ++s.id;// 错误:无法修改`id`不变字段
    }
}

限制

全局/局部和静态变量不能是__metadata:

module jaja;
__metadata int x = 2;
//错误:全局变量不能是`__metadata`
int fun()
{
    __metadata int y;
错误:局部变量不能是 `__metadata`
}

struct S
{
    private __metadata static int b;
//错误:静态变量不能是 `__metadata`
}

只能在@system代码中操作__metadata数据:

struct S
{
    private __metadata int* m;
}

int* bar() @safe
{
    S s;
    return s.m;
//错误,在`bar`@安全函数中无法访问`m`元数据.
//必须是@系统
}

shared

因为不变是隐式共享的,为了线程安全,按shared对待不变实例的__metadata字段:

struct S
{
    private __metadata int* p;
}
immutable S s;
static assert(is(typeof(s.p) == shared(int*)));

可从可变,const不变对象得到const对象,因此类型系统无法推导对象内__metadata字段应为共享或不共享.按非共享可变类型检查,const对象的__metadata字段,让用户理解代码并正确的强制转换:

shared int* q;
int* r;

struct A
{
    private __metadata int* p;
    bool isImmutable;

    this(shared int *p) immutable
    {
        this.p = p;
        isImmutable = true;
    }

    void fun() const
    {
        pragma(msg, typeof(p).stringof);
// typeof(p) => int*
        if (isImmutable)
            q = cast(shared int*) p;
        else
            r = p;
    }
}

void main()
{
    shared int* p
    immutable A ia = immutable A(p);
    const A ca;
    ia.fun();
    ca.fun();
}

可从可变,const不变对象得到inout对象
.__metadata字段的inout属性按一样类似对待.

pure

添加__metadata后,不变实例,按函数参数传递时,不会提供相同纯度保证:

struct S
{
    private __metadata int* p;

    void inc() immutable pure
    {
        *p += 1;
    }
}

void foo(ref immutable S a) pure
{
    a.inc();
}

int x;

void main()
{
    A b = A(&x);
    foo(b);
}

DIP之前,按强纯函数对待foo,但添加__metadata后,现在可通过元数据字段修改实例,因此foo成为弱纯函数.该DIP之后,仅当参数不包含元数据字段时,才按强纯函数对待带不变ref/pointer参数的函数.

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-14 23:31:36  更:2022-04-14 23:36:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:16:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码