C的限制关键字可以在C++中使用严格的混叠来模拟吗?
Can C's restrict keyword be emulated using strict aliasing in C++?
问题
C 中缺少C中的restrict
关键字,因此出于兴趣,我正在寻找一种在C 中模仿相同功能的方法。
具体来说,我希望以下等效:
// C
void func(S *restrict a, S *restrict b)
// C++
void func(noalias<S, 1> a, noalias<S, 2> b)
其中 noalias<T, n>
- 用
->
和*
访问T*
的行为就像CC_3 - 可以从
T*
构造(以便将函数称为func(t1, t2)
,其中t1
和t2
均为T*
类型) - 索引
n
指定了变量的"混叠类",因此可以假定noalias<T, n>
和noalias<T, m>
类型的变量永远不会对n!= m。
尝试
这是我深处有缺陷的解决方案:
template <typename T, int n>
class noalias
{
struct T2 : T {};
T *t;
public:
noalias(T *t_) : t(t_) {}
T2 *operator->() const {return static_cast<T2*>(t);} // <-- UB
};
使用->
访问时,它将内部存储的T*
投入到noalias<T, n>::T2*
并返回。由于这是每种n
的不同类型,因此严格的别名规则可确保它们永远不会别名。另外,由于T2
源自T
,因此返回的指针的行为就像T*
。太好了!
更好的是,代码编译和组装输出确认其具有所需的效果。
问题是static_cast
。如果t
确实指向T2
类型的对象,则可以。但是t
指向T
,所以这是UB。实际上,由于T2
是一个子类,它对T
没有任何额外的添加,因此可能具有相同的数据布局,因此T2*
上的成员访问将在T
中的相同偏移中寻找成员,并且一切都很好。<<<<<<<<<<<<<<<<<<<<<<<</p>
但是,具有n
依赖性类是严格的混叠所必需的,并且此类源自T
也是必要的,以便可以将指针视为T*
。因此,UB似乎不可避免。
问题
可以在C 14中完成此操作而不调用UB-可能使用完全不同的想法?
如果没有,那么我在C 1z中听说过"点运算符";这样可以吗?
如果以上,是否会出现在标准库中?
您可以使用 __restrict__
gcc扩展名进行联合/别名。
来自文档
除了允许限制指针外,您还可以指定有限的参考文献,该引用表明该参考文献在本地上下文中不明化。
void fn (int *__restrict__ rptr, int &__restrict__ rref)
{
/* ... */
}
在fn
的主体中,rptr
指向一个非偏见的整数,而RREF指的是(不同的)非偏置整数。您还可以通过使用__restrict__
作为成员函数预选程序来指定成员函数的该指针是否不明化。
void T::fn () __restrict__
{
/* ... */
}
在T::fn
的主体内,这将具有有效的定义T *__restrict__ const this
。请注意,__restrict__
成员函数预选赛的解释与const
或volatile
预选赛的解释不同,因为它应用于指针而不是对象。这与实施限制指针的其他编译器一致。
与所有最外部参数限定符一样,__restrict__
在函数定义匹配中被忽略。这意味着您只需要在函数定义中指定 __restrict__
,而不是在函数原型中指定。
也许我不明白您的问题,但是C限制关键字已从标准C 中删除,但几乎每个编译器都具有其" C限制"等效物:
Microsoft vs具有__declSpec(限制):https://msdn.microsoft.com/en-us/library/8bcxafdh.aspx
和GCC具有__限制__:https://gcc.gnu.org/onlinedocs/gcc/restrictal-pointers.html
如果您想要一个通用的定义,则可以使用#define的
#if defined(_MSC_VER)
#define RESTRICT __declspec(restrict)
#else
#define RESTRICT __restrict__
#endif
我不测试它,让我知道是不起作用
如果我们只是在谈论纯C 标准解决方案,运行时检查是唯一的办法。实际上,考虑到C的定义限制LVALUE预选赛的强度,我什至不确定是否可以,这是该对象只能通过限制指针访问。
添加类似限制语义的语义到c 的正确方法是使标准定义模板限制参考和受限制指针,以使得像普通参考和指针一样工作的虚拟版本可以在C 中进行编码。虽然可以生成在所有定义情况下按要求行事的模板,并在所有情况下都应调用UB,但除非编程编程以利用有关的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;
}
使用noalias
的用法几乎不会启用上述功能的优化:
int func(noalias<S, 1> a) {
*getPtr() += 10;
return 10 * a->i;
}
我的感觉是restrict
不能模仿,必须直接由编译器支持。
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- 如何使用Google Mock来模拟gettimeofday()
- C++中的"inline"关键字
- 如何确保C++函数在定义之前声明(如override关键字)
- G锁定铸造到基础上会释放模拟行为
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 落砂模拟碰撞检测C++和SFML
- 在gtest.中使用fff.h模拟系统API
- 谷歌模拟和覆盖关键字
- 用C#中的并集模拟C++嵌套结构
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- "super"关键字的 C++ 模拟
- C的限制关键字可以在C++中使用严格的混叠来模拟吗?
- 如何在c++中使用class中的static关键字来模拟Python中@classmethod的行为
- C# 的 C++ 模拟"is"关键字