我需要一种安全的方法来在任意POD类型之间进行别名,符合ISO-C++ 11,明确考虑n3242或更高版本的3.10/10和3.11.这里有很多关于严格别名的问题,其中大部分都是关于C而不是C++.我找到了一个使用联合的C的"解决方案",可能使用了这个部分
联合类型,包括其元素或非静态数据成员中的上述类型之一
从那我建立了这个.
#include <iostream>
template <typename T, typename U>
T& access_as(U* p)
{
union dummy_union
{
U dummy;
T destination;
};
dummy_union* u = (dummy_union*)p;
return u->destination;
}
struct test
{
short s;
int i;
};
int main()
{
int buf[2];
static_assert(sizeof(buf) >= sizeof(double), "");
static_assert(sizeof(buf) >= sizeof(test), "");
access_as<double>(buf) = 42.1337;
std::cout << access_as<double>(buf) << '\n';
access_as<test>(buf).s = 42;
access_as<test>(buf).i = 1234;
std::cout << access_as<test>(buf).s << '\n';
std::cout << access_as<test>(buf).i << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,可以肯定的是,该计划是否符合标准?*
它没有给出任何警告,并且在使用MinGW/GCC 4.6.2进行编译时工作正常: …
我已经在Stack Overflow中阅读了很多关于严格别名的QA,但它们都很常见,而且讨论总是倾向于引用C++标准的深层细节,这些细节几乎总是很难理解.特别是在标准时,不要直接说话,而是用泥泞不清楚的方式描述.所以,我的问题可能是这里有大量质量保证的重复,但是,请回答一个具体的问题:
这是做"nonalias_cast"的正确方法吗?:
template<class OUT, class IN>
inline auto nonalias_cast(IN *data) {
char *tmp = reinterpret_cast<char *>(data);
return reinterpret_cast<OUT>(tmp);
}
float f = 3.14;
unsigned *u = nonalias_cast<unsigned *>(&f);
*u = 0x3f800000;
// now f should be equal 1.0
Run Code Online (Sandbox Code Playgroud)
我猜答案是否定的.但是有什么好的解决方法吗?当然,除了禁用严格别名标志.联盟也不是一个方便的选择,除非有一种方法在nonalias_cast函数体内部适合联合黑客.memcpy这里也不是一个选项 - 数据更改应该是同步的.
一个不可能的梦想或一个难以捉摸的现实?
UPD:
好的,既然我们得到了一个否定答案"是否可能?" 问题,我想问你一个困扰我的额外问题:
将如何您解决这个任务?我的意思是有很多实际的任务,更多的是要求"玩一点点"的方法.例如,假设您必须像这样编写IEEE-754浮点转换器.我更关注问题的实际方面:如何有一个解决方法来实现目标?至少在"#$ $的痛苦"方式.