Can C';可以在C+;中使用严格别名模拟s restrict关键字+;? 问题 >代码>限制C中的关键字在C++中丢失,因此出于兴趣,我正在寻找一种方法来模拟C++中的相同特性。p>

Can C';可以在C+;中使用严格别名模拟s restrict关键字+;? 问题 >代码>限制C中的关键字在C++中丢失,因此出于兴趣,我正在寻找一种方法来模拟C++中的相同特性。p>,c++,c++14,restrict,strict-aliasing,C++,C++14,Restrict,Strict Aliasing,具体而言,我希望以下内容等效: // C void func(S *restrict a, S *restrict b) // C++ void func(noalias<S, 1> a, noalias<S, 2> b) 当使用->访问时,它将内部存储的T*强制转换为noalias::T2*,并返回该值。由于这是每个n的不同类型,因此严格的别名规则确保它们永远不会使用别名。此外,由于T2源自T,因此返回的指针的行为与T*类似。太好了 更妙的是,代码经过编译,程序集输

具体而言,我希望以下内容等效:

// C
void func(S *restrict a, S *restrict b)

// C++
void func(noalias<S, 1> a, noalias<S, 2> b)
当使用
->
访问时,它将内部存储的
T*
强制转换为
noalias::T2*
,并返回该值。由于这是每个
n
的不同类型,因此严格的别名规则确保它们永远不会使用别名。此外,由于
T2
源自
T
,因此返回的指针的行为与
T*
类似。太好了

更妙的是,代码经过编译,程序集输出确认它具有所需的效果

问题在于
静态\u cast
。如果
t
确实指向
T2
类型的对象,那么这就可以了。但是
t
指向一个
t
,所以这是UB。实际上,由于
T2
是一个子类,它不向
T
添加任何额外内容,因此
T2*
上的成员访问可能具有相同的数据布局,因此
T2*
上的成员将查找与
T
中相同偏移量的成员,一切都会很好

但是有一个依赖于
n
的类对于严格的别名是必需的,并且这个类派生自
T
也是必需的,这样指针就可以像对待
T*
一样对待。所以UB似乎不可避免

问题
  • 在c++14中,不调用UB(可能使用完全不同的想法)可以做到这一点吗

  • 如果没有,那么我听说过c++1z中的“点运算符”;这有可能吗

  • 如果出现上述情况,标准库中是否会出现类似于noalias的内容


  • 在C++中添加类限制语义的正确方法是,对受限引用和受限指针具有标准定义模板,这样可以像普通引用和指针一样工作的虚拟版本可以用C++编码。虽然可以生成在所有已定义的情况下均按要求运行的模板,并在所有不应定义的情况下调用UB,但这样做如果不会产生反效果,那么将是无用的,除非编译器被编程为利用所述UB来促进此类优化。在代码使用标准定义类型的情况下,编写编译器以利用此类优化比试图在用户类型中识别可利用的模式更容易、更有效,而且也不太可能产生不想要的副作用。

    我认为您的解决方案没有完全达到预期目标,即使不存在已知的UB。毕竟,所有实际数据访问都发生在内置类型级别。如果
    decltype(a->i)
    int
    ,并且您的函数操作
    int*
    指针,那么在某些情况下,编译器仍然应该假设这些指针可以别名
    a->i

    例如:

    int func(noalias<S, 1> a) {
        int s = 0;
        int* p = getPtr();
        for ( int i = 0; i < 10; ++i ) {
            ++*p;
            s += a->i;
        }
        return s;
    }
    

    <>我的感觉是<>代码>限制/代码>不能直接编译,必须直接由编译器支持。

    也许我不理解你的问题,但是C限制关键字从标准C++中删除,但是几乎每个编译器都有他们的“C限制”等价项:

    Microsoft VS有u declspec(限制):

    GCC有______;限制_;

    如果你想要一个通用的定义,你可以使用#define's


    我不测试它,让我知道它不起作用

    您可以使用
    \uuuuuuuuuuuu
    GCC扩展来取消/消除混叠

    从文件中

    除了允许受限指针外,还可以指定受限引用,这表明该引用在本地上下文中没有别名

    void fn (int *__restrict__ rptr, int &__restrict__ rref)
    {
    /* ... */
    }
    
    fn
    的主体中,
    rptr
    指向一个未关联的整数,而rref指的是一个(不同的)未关联的整数。 您还可以通过使用
    \uuuu restrict\uuuu
    作为成员函数限定符来指定成员函数的this指针是否未关联

    void T::fn () __restrict__
    {
    /* ... */
    }
    
    T::fn
    的主体中,这将具有有效的定义
    T*\uuuu restrict\uuuuu.const this
    。请注意,
    \uuuu restrict\uuu
    成员函数限定符的解释不同于
    const
    volatile
    限定符的解释,因为它应用于指针而不是对象。这与实现受限指针的其他编译器是一致的


    与所有最外层的参数限定符一样,
    \uuuuuu restrict\uuuu
    在函数定义匹配中被忽略。这意味着您只需要在函数定义中指定“代码>”、“限制”、“代码”,而不是在函数原型中。

    如果我们只讨论纯C++标准解决方案,则运行时检查是唯一的方法。考虑到C的restrict左值限定符定义的强度,我甚至不确定这是否可行,也就是说,对象只能通过restrict指针访问。

    您可能想看看她restrict是一个关键字。你不能实现它,就像你不能实现“自动”你自己一样。我会在问题标题中写“模仿使用可能不同语法的行为”,而不是“模仿”,但我喜欢让事情简单明了,希望人们能理智地填补空白。“实际上,由于T2是一个子类,它不会给T增加任何额外的内容,因此它可能具有相同的数据布局”,除非
    T*
    实际上是一个
    D*
    ,其中
    D
    是从
    T
    派生出来的类。关于
    D*
    的公平点-它也会导致
    动态转换的问题
    (您必须在中间转换为
    T*
    ),但我不认为
    T
    -子结构的
    T2
    d
    的数据布局会有任何差异
    #if defined(_MSC_VER)
    #define RESTRICT __declspec(restrict)
    #else
    #define RESTRICT __restrict__
    #endif
    
    void fn (int *__restrict__ rptr, int &__restrict__ rref)
    {
    /* ... */
    }
    
    void T::fn () __restrict__
    {
    /* ... */
    }